POJ1273 USACO 4.2.1 Drainage Ditches CodeVS1993草地排水 网络流 最大流 SAP
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
传送门 - POJ
传送门 - CodeVS
题意概括
给出一个图,告诉你边和容量,起点是1,汇点是n,让你求最大流。
题解
最大流模板题。
SAP跑一发!
学习网络流
代码
#include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cmath> using namespace std; const int N=200+5,M=N*2; int n,m; struct edge{ int x,y,cap,flow,nxt; // x,y 边的两个节点, cap 容量, flow 流量, nxt 指向 x 的下一条边 }; struct gragh{ int cnt,fst[N],dist[N],s,t,num[N],cur[N],p[N]; int q[N],head,tail; edge e[M]; void set(int S,int T){//初始化 s=S,t=T,cnt=1; memset(fst,0,sizeof fst); memset(e,0,sizeof e); } void add(int a,int b,int c){ // 建立正向边,容量为c cnt++; e[cnt].x=a,e[cnt].y=b,e[cnt].cap=c,e[cnt].flow=0; e[cnt].nxt=fst[a],fst[a]=cnt; // 建立反向边,容量为0 cnt++; e[cnt].x=b,e[cnt].y=a,e[cnt].cap=0,e[cnt].flow=0; e[cnt].nxt=fst[b],fst[b]=cnt; } void re_bfs(){ memset(dist,-1,sizeof dist); memset(q,0,sizeof q); head=tail=dist[t]=0; q[++tail]=t; while (head<tail) for (int x=q[++head],i=fst[x];i;i=e[i].nxt){ int y=e[i].y; if (e[i].cap==0&&dist[y]==-1) q[++tail]=y,dist[y]=dist[x]+1; } //bfs给所有的节点分层,得到每个点到达汇点的一种路径的边数 //据说可以达到常数级优化的效果 for (int i=1;i<=n;i++) if (dist[i]==-1) dist[i]=n; } int Augment(int &point){ int ex_Flow=1<<25; for (int i=t;i!=s;i=e[p[i]].x) if (e[p[i]].cap-e[p[i]].flow<ex_Flow) ex_Flow=e[p[i]].cap-e[p[i]].flow,point=e[p[i]].x; for (int i=t;i!=s;i=e[p[i]].x){ e[p[i]].flow+=ex_Flow; e[p[i]^1].flow-=ex_Flow; } return ex_Flow; } int ISAP(){ int x,y,MaxFlow=0; memset(num,0,sizeof num); for (int i=1;i<=n;i++) cur[i]=fst[i];//保存每个节点增广到的弧, //作为当前弧优化的重要部分 for (int i=1;i<=n;i++) num[dist[i]]++;//算出每一个层次当前的节点数量 x=s; while (dist[s]<n){ if (x==t){ MaxFlow+=Augment(x); continue; } bool found=0; for (int i=cur[x];i;i=e[i].nxt){ y=e[i].y; if (dist[y]+1==dist[x]&&e[i].cap>e[i].flow){ p[y]=cur[x]=i,x=y,found=1; break; }//找到一条可能为增广路的路径 } if (!found){ int d=n+1; for (int i=fst[x];i;i=e[i].nxt) if (e[i].cap>e[i].flow) y=e[i].y,d=min(d,dist[y]+1); if (!(--num[dist[x]])) return MaxFlow;//传说中的GAP优化 num[dist[x]=d]++; cur[x]=fst[x]; if (x!=s) x=e[p[x]].x; } } return MaxFlow; } }g; int main(){ while (~scanf("%d%d",&m,&n)){ g.set(1,n); for (int i=1,a,b,c;i<=m;i++) scanf("%d%d%d",&a,&b,&c),g.add(a,b,c); g.re_bfs(); printf("%d\n",g.ISAP()); } return 0; }