网络最大流模板题,题意很直白。
给出源点,汇点,点个数,边条数,以及每条边的流量,求源点到汇点的最大流量。
最大流经典算法Dinic算法,理论复杂度\(O(n^2m)\),但是实际运用中远远达不到这个上界,可以说是比较容易实现的效率最高的网络流算法之一,一般能处理\(10^4 -10^5\)规模的网络,特别的地,Dinic算法求解二分图最大匹配的理论时间复杂度为\(O(m\sqrt{n})\),实际表现则更快。
当前弧优化
一个点可能有多条出边,在DFS寻找增广路的时候,如果遍历该点的出边时,发现有些边已经没有剩余流量时,记录下当前遍历的点,下次再碰到该点时,无需从头开始遍历,直接从记录的位置开始遍历(因为记录位置之前的出边都没有剩余流量了,没有遍历的必要,代码实现:边使用链式前向星存储,使用额外数组cur[]复制head[]的值,实现cur代替head进行遍历,并及时更新cur的值,也就是修改头结点的指向)。
多路增广优化
爆点优化
当DFS遍历时发现一个点没有了流出的流量,则把该点的deep值置为-2,将无用的点抛弃,下次无需再遍历。
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define sf(x) scanf("%d",&(x))
const int MAXN=1e4+5;
const int MAXM=1e5+5;
const int INF=1e8+10;
int N,M,S,T;
struct node{int v,flow,next;}edge[MAXM*2];
int head[MAXN],cur[MAXN],num=0;//注意这里必须从0开始
inline void add(int x,int y,int z)
{
edge[num].v=y;edge[num].flow=z;
edge[num].next=head[x];head[x]=num++;
}
queue<int> q;
int deep[MAXN];
bool BFS()
{
memset(deep,0,sizeof(deep));
deep[S]=1;
q.push(S);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
if(!deep[edge[i].v]&&edge[i].flow)
{
deep[edge[i].v]=deep[u]+1;
q.push(edge[i].v);
}
}
return deep[T];
}
int DFS(int now,int nowflow)
{
if(now==T) return nowflow;
int totflow=0;//从这个点总共可以增广多少流量
for(int i=cur[now];i!=-1;i=edge[i].next)
{
cur[now]=i;//当前弧优化,记录压榨到哪条边
if(deep[edge[i].v]==deep[now]+1&&edge[i].flow)//只有满足距离要求与流量要求的点才能进行增广
{
int canflow=DFS(edge[i].v,min(nowflow,edge[i].flow));
if(!canflow)continue;//当可增广的流量大于0,更新
edge[i].flow-=canflow;edge[i^1].flow+=canflow;//增广
totflow+=canflow;
nowflow-=canflow;
if(nowflow<=0) break; //当前点已经没有流量 快100ms
}
}
if(!totflow)deep[now]=-2;//爆点优化,该点已经没有剩余流量,证明不必要的点下一次不需要遍历
return totflow;
}
void Dinic()
{
int ans=0;
while(BFS())//每次构造分层图
{
memcpy(cur,head,sizeof(head)); //当前弧优化
ans+=DFS(S,INF);//进行增广
}
printf("%d",ans);
}
int main()
{
sf(N);sf(M);sf(S);sf(T);
memset(head,-1,sizeof(head));
for(int i=1;i<=M;i++)
{
int x,y,z;
sf(x);sf(y);sf(z);
add(x,y,z),add(y,x,0);
}
Dinic();
return 0;
}
参考博文:
https://www.cnblogs.com/zwfymqz/p/8280746.html#_label4
https://www.bilibili.com/video/av21945401?from=search&seid=17416394282430843291
https://www.cnblogs.com/SYCstudio/p/7260613.html
原文:https://www.cnblogs.com/sstealer/p/12207600.html