概述
网络流EK算法 数据结构:队列 主要操作:广搜 记录路径 更新 能解决的问题:最大流(最小割) 复杂度:O(MV)v指最大容量,M指边数。 新名词: 1.增广路:从源点source到tink的一条简单路,如果路上的每条边(u,v)的可改进量均大于0,则称这条路为一条增广路。 增广路定理:网络达到最大流量当且仅当不存在增广路。 增广路算法:从一个可行流开始不断的寻找可增广路,然后沿着它增广,直到它不存在。 2.反向弧:如果有一条弧(u,v),那么再进行网络流算法时,要对它建立反向弧(v,u),反向弧的容量为0,与正向弧相反,正向弧减少容量时,反向弧增加容量。建立反向弧能更多的增广,使网络流算法正确。(无法给出证明) 3.可行弧:在EK算法中指可从u到v增加流量(也就是容量不为0)。 4.可行路:从源点source到tink的有可行弧构成的路径叫做可行路。 具体操作: 1.建立网络(正向弧+反向弧) 2.从源点出发,广搜一条最短可行路(即最先到达汇点tink的那条路),每次到达一个点用pre数组记录是由那条边过来的(为后面减小流量做准备) 3.到达汇点tink时,按照pre数组记录的,从可行路中找一条容量最小的进行容量减少。即找到了一条割边。 4.重复操作2.3,直到无法到达汇点,算法结束,即找到了最大流,算法结束。 推荐水题:USACO 4.2.1 纯网络流算法,可用来试EK的正确性,但EK只能拿50分!
1 #include<cstdio> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 using namespace std; 6 7 #define INF 1000000 8 9 struct Edge 10 { 11 int x,y,flow,next,op;//flow表示当前边的容量 op表示正向弧所对应的反向弧在边表中的位置 12 }; 13 14 Edge map[200]; 15 int que[20000]; 16 bool b[500];//用b数组记录是否入队,可以防止重复入队,因为有反向弧和环!! 17 int source,tink,n,m,tot,ans,head,tail; 18 int first[500]; 19 int pre[500]; 20 21 int fmin(int x ,int y) 22 { 23 if (x<y) return x; 24 else return y; 25 } 26 27 void Build(int x ,int y ,int c) 28 { 29 tot++;//正向弧 30 map[tot].x=x; 31 map[tot].y=y; 32 map[tot].flow=c; 33 map[tot].next=first[x]; 34 first[x]=tot; 35 map[tot].op=tot+1; 36 tot++;//反向弧 37 map[tot].x=y; 38 map[tot].y=x; 39 map[tot].flow=0;//反向弧容量为0 40 map[tot].next=first[x]; 41 first[x]=tot; 42 map[tot].op=tot-1; 43 } 44 45 void init() 46 { 47 memset(first,0,sizeof(first)); 48 tot=0; ans=0; 49 scanf("%d%d",&m,&n); 50 for (int i=1; i<=m; i++) 51 { 52 int x,y,c; 53 scanf("%d%d%d",&x,&y,&c); 54 Build(x,y,c); 55 } 56 source=n+1; tink=n+2;//手动建立源点和汇点,看题目要求! 57 Build(source,1,INF); 58 Build(n,tink,INF); 59 } 60 61 bool Bfs() 62 { 63 memset(b,false,sizeof(b)); 64 head=1; tail=1; que[1]=source; b[source]=true; pre[source]=-1;//没有可以到源点的路 65 while (head<=tail) 66 { 67 int x=que[head]; 68 int t=first[x]; 69 while (t>0) 70 { 71 int y=map[t].y; 72 if (map[t].flow>0 && b[y]==false)//找到一条可行弧 73 { 74 tail++; 75 que[tail]=y; 76 b[y]=true; 77 pre[y]=t;//路径记录 78 if (y==tink) return true;//到达汇点,退出广搜 79 } 80 t=map[t].next; 81 } 82 head++; 83 b[x]=false; 84 } 85 return false; 86 } 87 88 void updata() 89 { 90 int Min=INF; 91 for (int p=pre[tink];p!=-1;p=pre[map[p].x]) 92 { 93 Min=fmin(Min , map[p].flow);//找可行路中的最小容量 94 } 95 for (int p=pre[tink];p!=-1;p=pre[map[p].x])//更新容量过程 96 { 97 map[p].flow-=Min; 98 map[map[p].op].flow+=Min;//反向弧增加容量 99 } 100 ans+=Min; 101 } 102 103 void EK() 104 { 105 106 while (Bfs()==true) 107 { 108 updata(); 109 } 110 printf("%dn",ans); 111 } 112 113 int main() 114 { 115 freopen("ditch.in","r",stdin); 116 freopen("ditch.out","w",stdout); 117 init(); 118 EK(); 119 return 0; 120 fclose(stdin); fclose(stdout); 121 }
转载于:https://www.cnblogs.com/acSzz/archive/2012/05/01/2477742.html
最后
以上就是还单身大炮为你收集整理的网络流 Edmons-Karp 算法讲解的全部内容,希望文章能够帮你解决网络流 Edmons-Karp 算法讲解所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复