/* 一定要建边权为0的反向边 别忘了dinic的三个优化: 1、当前弧优化,访问这个点的出边时,从上一次访问的下一条边开始 2、当增广到某个点时,增广过程中,已出去的流量==进来的,停止增广;增广完毕时,出去的流量<进来的流量,标记这个点,以后不再访问此点 3、分层时,找到汇点后即刻return,不要等到队列为空 */ #include<iostream> #include<cstdio> #include<queue> #define maxn 10010 using namespace std; int n,m,ans,head[maxn],cur[maxn],f[maxn],lev[maxn],num=1,s,t; struct node{ int to,pre,cap; }e[100010*2]; void Insert(int from,int to,int v){ e[++num].to=to; e[num].cap=v; e[num].pre=head[from]; head[from]=num; } bool bfs(int st){ queue<int>q; q.push(st); for(int i=1;i<=n;i++)cur[i]=head[i],lev[i]=-1; lev[st]=0; while(!q.empty()){ int now=q.front();q.pop(); for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(lev[to]==-1&&e[i].cap>0){ lev[to]=lev[now]+1; q.push(to); if(to==t)return 1; } } } return 0; } int dinic(int now,int flow){ if(now==t)return flow; int rest=0,delta; for(int &i=cur[now];i;i=e[i].pre){ int to=e[i].to; if(e[i].cap>0&&lev[to]==lev[now]+1){ delta=dinic(to,min(flow-rest,e[i].cap)); if(delta){ e[i].cap-=delta;e[i^1].cap+=delta; rest+=delta;if(rest==flow)break; } } } if(rest!=flow)lev[now]=-1; return rest; } int main(){ scanf("%d%d%d%d",&n,&m,&s,&t); int x,y,z; for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); Insert(x,y,z);Insert(y,x,0); } while(bfs(s)) ans+=dinic(s,0x7fffffff); printf("%d",ans); }
原文:https://www.cnblogs.com/thmyl/p/13284322.html