//求轻喷 ↗大神右上角
因为网络流的模型实在是太经典了,于是在这里就不再多废口舌讲模型,看下面这题吧
Dinic算法核心就是:
①在残量网络上跑层次图
②用dfs在层次图上增广,直到不存在增广路
③重复上述步骤直到不能再增广
用一张图来表示Dinic的流程就是这样的:

Dinic的思想概念是很好理解的,它的总时间复杂度为O(n²m),实际上Dinic跑的比这个理论上的时间复杂度要快的多。
下面给出上面那题的AC代码做模板用:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#define oo (1<<30)
#define N 100005
#define M 1000005
int n,S,T,ll,son[N],d[N],q[N],link[M],next[M],cap[M],opp[M];
#define min(a,b) (a<b?a:b)
bool bfs(){
int x,y,l=1,r=1;
memset(d,-1,sizeof(int)*(n+5));
q[1]=S;d[S]=0;
while(l<=r){
x=q[l++];
for(int i=son[x];i!=-1;i=next[i]){
y=link[i];
if(cap[i]&&d[y]==-1){
d[y]=d[x]+1;q[++r]=y;
if(y==T)return 1;
}
}
}
return 0;
}
int find(int now,int flow){
int ret,y,w=0;
if(now==T)return flow;
for(int i=son[now];i!=-1&&w<flow;i=next[i]){
y=link[i];
if(cap[i]&&d[y]==d[now]+1&&(ret=find(y,min(flow-w,cap[i]))))
cap[i]-=ret,cap[opp[i]]+=ret,w+=ret;
}
if(!w)d[now]=-1;
return w;
}
void addedge(int x,int y,int z){
link[++ll]=y;next[ll]=son[x];son[x]=ll;cap[ll]=z;opp[ll]=ll+1;
link[++ll]=x;next[ll]=son[y];son[y]=ll;cap[ll]=0;opp[ll]=ll-1;
}
int main(){
int m,x,y,z,ans,flow;
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
while(~scanf("%d%d",&m,&n)){
memset(son,-1,sizeof(int)*(n+5));
S=1;T=n;ans=0;ll=0;
for(int i=1;i<=m;++i)
scanf("%d%d%d",&x,&y,&z),addedge(x,y,z);
while(bfs())
while(1){
flow=find(S,oo);
if(!flow)break;
ans+=flow;
}
printf("%d\n",ans);
}
}
其实网络流注重的并非是怎么算网络流,用什么算法,关键是建模
习题:
loading...
评论 (0)