//EK,SAP,DINIC三种算法以及它们的表和阵两个版本的效率,已在sicily1423. 魔王bug的2色定理上验证过, //显然SAP,DINIC要快很多,SAP和DINIC相差不大。但因为DINIC每次要重新构层次图,可能相对会慢一点。 const int VMAX = 500; int n,m,s,t; int r[VMAX+10][VMAX+10]; int gap[VMAX+10],pre[VMAX+10],dis[VMAX+10]; //int cur[VMAX+10]; //看过有些代码加了这个,可能是优化吧 int sap(int N) //N为点数(包括源汇) { memset(dis,0,sizeof(dis)); //重要优化,可以从dis全0开始BFS memset(gap,0,sizeof(gap)); //memset(cur,0,sizeof(cur)); gap[0]=N; int u=pre[s]=s,ca=inf,ans=0; while (dis[s]<N) //dis[s]顶多为N-1,如果推出dis[s]>=N,说明已为增广路,算法结束 { while (1) { bool flag=false; //标记是否找到容许边 for (int i=0;i<N;i++) //for (int i=cur[u];i<=t;i++) if (r[u][i] && dis[u]==dis[i]+1) { //cur[u]=i; ca=min(ca,r[u][i]); pre[i]=u; u=i; if (i==t) //找到汇点,增流,再从源点重新开始 { ans+=ca; for (u=pre[u];i!=s;i=u,u=pre[u]) { r[u][i]-=ca; r[i][u]+=ca; } ca=inf; } flag=true; break; } if(!flag) break; } //修改顶点标号 int Min=N; //这里Min不能取inf,因为如果下面Min没被替换就会导致RE for (int i=0;i<N;i++) if (r[u][i] && dis[i]<Min) Min=dis[i]; //Min=dis[i],cur[u]=i; if (--gap[dis[u]] == 0) break; //间隙优化 gap[dis[u]=Min+1]++; u=pre[u]; } return ans; }