/* sap学了很长时间,一直不敢下手写,结果就是不写永远不会真正的理解算法的含义,sap理论很多算法书上都有讲解,但我还是建议看数学专业 图论的书,比如 《有向图的理论,算法及应用》,这本书的内容非常棒,相信看过的都知道吧,比其他算法书上讲的透多了。
SAP有个优化就是 当出现断链时,就可以直接退出,还有个优化是当前弧的优化,这两个优化只需要一句话+一个数组就解决了,相当实惠,好的ISAP执行的效率真的非常高,我写的ISAP用的是链式前向星法表示。
这个就算是模板了吧,虽然写的不是很好。。*/
#include<iostream> #include<cstdio> #include<memory.h> #include<cmath> using namespace std; #define MAXN 500 #define MAXE 40000 #define INF 0x7fffffff long ne,nv,tmp,s,t,index; struct Edge{ long next,pair; long v,cap,flow; }edge[MAXE]; long net[MAXN]; long ISAP() { long numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN]; long cur_flow,max_flow,u,tmp,neck,i; memset(dist,0,sizeof(dist)); memset(numb,0,sizeof(numb)); memset(pre,-1,sizeof(pre)); for(i = 1 ; i <= nv ; ++i) curedge[i] = net[i]; numb[nv] = nv; max_flow = 0; u = s; while(dist[s] < nv) { /* first , check if has augmemt flow */ if(u == t) { cur_flow = INF; for(i = s; i != t;i = edge[curedge[i]].v) { if(cur_flow > edge[curedge[i]].cap) { neck = i; cur_flow = edge[curedge[i]].cap; } } for(i = s; i != t; i = edge[curedge[i]].v) { tmp = curedge[i]; edge[tmp].cap -= cur_flow; edge[tmp].flow += cur_flow; tmp = edge[tmp].pair; edge[tmp].cap += cur_flow; edge[tmp].flow -= cur_flow; } max_flow += cur_flow; u = neck; } /* if .... else ... */ for(i = curedge[u]; i != -1; i = edge[i].next) if(edge[i].cap > 0 && dist[u] == dist[edge[i].v]+1) break; if(i != -1) { curedge[u] = i; pre[edge[i].v] = u; u = edge[i].v; }else{ if(0 == --numb[dist[u]]) break; curedge[u] = net[u]; for(tmp = nv,i = net[u]; i != -1; i = edge[i].next) if(edge[i].cap > 0) tmp = tmp<dist[edge[i].v]?tmp:dist[edge[i].v]; dist[u] = tmp + 1; ++numb[dist[u]]; if(u != s) u = pre[u]; } } return max_flow; } int main() { long i,j,np,nc,m,n; long a,b,val; long g[MAXN][MAXN]; while(scanf("%d%d",&ne,&nv)!=EOF) { s = 1; t = nv; memset(g,0,sizeof(g)); memset(net,-1,sizeof(net)); for(i=0;i<ne;++i) { scanf("%ld%ld%ld",&a,&b,&val); g[a][b] += val; } for(i=1;i<=nv;++i) for(j = i; j <= nv;++j) if(g[i][j]||g[j][i]) { edge[index].next = net[i]; edge[index].v = j; edge[index].cap = g[i][j]; edge[index].flow = 0; edge[index].pair = index+1; net[i] = index++; edge[index].next = net[j]; edge[index].v = i; edge[index].cap = g[j][i]; edge[index].flow = 0; edge[index].pair = index-1; net[j] = index++; } printf("%ld\n",ISAP()); } return 0; }