调试了一晚上,orz..
在加了间隙优化后,保守估计,距离标号算法比Edmond-Karp算法要快至少两倍
对HOJ1228实测表明 距离标号 的效率是 Edmond-Karp 的 十倍.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | #include <iostream> #include <queue> #define msize 1024 //最大顶点数目 using namespace std; int d[msize]; //标号 int r[msize][msize]; //残留网络,初始为原图 int num[msize]; //num[i]表示标号为i的顶点数有多少 int pre[msize]; int n,m,s,t; //m个顶点,n条边,从源点s到汇点t void ini_d() //BFS计算标号,汇点t标号为0 { int k; queue<int>Q; memset(d,1,sizeof(d)); memset(num,0,sizeof(num)); Q.push(t); d[t]=0; num[0]=1; while (!Q.empty()) { k=Q.front(),Q.pop(); for (int i=0;i<m;i++) { if (d[i]>=m&&r[i][k]>0) { d[i]=d[k]+1; Q.push(i); num[d[i]]++; } } } } int findAlowArc(int i) //从i出发寻找允许弧 { int j; for (j=0;j<m;j++) if (r[i][j]>0&&d[i]==d[j]+1) return j; return -1; } int reLable(int i) //重新标号 { int mm=INT_MAX; for (int j=0;j<m;j++) if (r[i][j]>0) mm=min(mm,d[j]+1); return mm==INT_MAX?m:mm; } int maxFlow(int s,int t) //从源点s出发的最大流 { int flow=0,i=s,j; int delta; //增量 memset(pre,-1,sizeof(pre)); while (d[s]<m) { j=findAlowArc(i); if (j>=0) { pre[j]=i; i=j; if (i==t) //更新残留网络 { delta=INT_MAX; for (i=t;i!=s;i=pre[i]) delta=min(delta,r[pre[i]][i]); for (i=t;i!=s;i=pre[i]) r[pre[i]][i] -= delta, r[i][pre[i]] += delta; flow += delta; } } else { int x=reLable(i); //重新标号 num[x]++; num[d[i]]–; if (num[d[i]]==0) return flow; //间隙优化 d[i]=x; if (i!=s) i=pre[i]; } } return flow; } |
















orz………
Orz,期待下一个模板~
赶紧把最小费用最大流模板搞出来~找不到啊~
模板阿,膜拜啊。。。
orz….
写得通俗易懂,
如果能把最小费用最大流的也弄出来就好了,
顺便问一个问题,网络流有那么种算法,像什么预推流啊,dinic,增广路,一般到底要掌握哪些?这些算法各有什么优点?
Re newmyl:
按照教练所传授的经验,距离标号能对付一般的基本网络流.
另外,dinic也应该是要掌握的吧,可惜我不懂,只会照模板敲.
我只是一个ACM的新手,学识浅薄,见笑了.
学长,我来看看!
相当有用啊,ORZ一下
请问这里:
for (i=t;i!=s;i=pre[i]) r[pre[i]][i] -= delta, r[i][pre[i]] += delta;
r[i][pre[i]] += delta; 这句是为什么?
@chhaya
这个…因为很久没做过题了,网络流算法快忘光了~~不好意思 /yun
int mm=INT_MAX;;
for (int j=0;j0) mm=min(mm,d[j]+1);
return mm==INT_MAX?m:mm;
-》》
int mm=m;
for (int j=0;j0) mm=min(mm,d[j]+1);
return mm;
你是怎么想的?
@最大牛最小哥 这是若干年前写的代码,很抱歉我已经不记得当时的想法了。
我对这个程序有一点不明白,我觉得这个程序是一个死循环,问题出在61行处。
奥,我明白是怎么一个回事啦,谢谢你的程序