最近在看网络流,把几个常用的算法总结下,正确性的证明和一些理论的东西就不写了,参看算法导论和神牛们的论文,我只写算法的理解和实现模板。
Ford-Fulkerson方法 每次找增广路,把这条路上的所有点的流量加上这条路上的残余容量,再找新的增广路,直到找不到为止,它有很多种实现方法,下面给出算法导论上的伪代码
Ford_Fulkerson( G, s, t ){ for each edge( u, v )∈E[G] do f[u,v]= 0 f[v,u]= 0 while there exists a path p from s to t in the residual network Gf do Cf(p)= min{ Cf(u,v) | (u,v) is in p } for each edge(u,v) in p do f[u,v]+= Cf(p) f[v,u]= -f[u,v]
Edmonds-Karp算法 就是用广度优先搜索来实现Ford-Fulkerson方法中对增广路径的计算,时间复杂度为O(VE 2) (代码参考NOCOW)
#define VMAX 201 int n, m; //分别表示图的边数和顶点数 int c[VMAX][VMAX]; int Edmonds_Karp( int s, int t ){ //输入源点和汇点 int p, q, queue[VMAX], u, v, pre[VMAX], flow= 0, aug; while(true){ memset(pre,-1,sizeof(pre)); //记录父节点 for( queue[p=q=0]=s; p<=q; p++ ){ //广度优先搜索 u= queue[p]; for( v=0; v<m&&pre[t]<0; v++ ) if( c[u][v]>0 && pre[v]<0 ) pre[v]=u, queue[++q]=v; if( pre[t]>=0 ) break; } if( pre[t]<0 ) break; //不存在增广路 aug= 0x7fff; //记录最小残留容量 for( u=pre[v=t]; v!=s; v=u,u=pre[u] ) if(c[u][v]<aug) aug=c[u][v]; for( u=pre[v=t]; v!=s; v=u,u=pre[u] ) c[u][v]-=aug, c[v][u]+=aug; flow+= aug; } return flow; }
|
|