网络流:最大流之EK算法
网络流主要解决三种问题:最大流、最小流和费用流。
最大流算法主要有三种:EK算法、Dinic算法、SAP算法
本篇博客是关于EK算法的。最坏的情况下,EK算法将达到复杂度O(VE2)。
1 #include <iostream> 2 #include <queue> 3 #include<string.h> 4 using namespace std; 5 #define arraysize 201 6 int maxData = 0x7fffffff; 7 int capacity[arraysize][arraysize]; //记录残留网络的容量 8 int flow[arraysize]; //标记从源点到当前节点实际还剩多少流量可用 9 int pre[arraysize]; //标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中 10 int n,m; 11 queue<int> myqueue; 12 int BFS(int src,int des) 13 { 14 int i,j; 15 while(!myqueue.empty()) //队列清空 16 myqueue.pop(); 17 for(i=1;i<m+1;++i) 18 { 19 pre[i]=-1; 20 } 21 pre[src]=0; 22 flow[src]= maxData; 23 myqueue.push(src); 24 while(!myqueue.empty()) 25 { 26 int index = myqueue.front(); 27 myqueue.pop(); 28 if(index == des) //找到了增广路径 29 break; 30 for(i=1;i<m+1;++i) 31 { 32 if(i!=src && capacity[index][i]>0 && pre[i]==-1) 33 { 34 pre[i] = index; //记录前驱 35 flow[i] = min(capacity[index][i],flow[index]); //关键:迭代的找到增量 36 myqueue.push(i); 37 } 38 } 39 } 40 if(pre[des]==-1) //残留图中不再存在增广路径 41 return -1; 42 else 43 return flow[des]; 44 } 45 int maxFlow(int src,int des) 46 { 47 int increasement= 0; 48 int sumflow = 0; 49 while((increasement=BFS(src,des))!=-1) 50 { 51 int k = des; //利用前驱寻找路径 52 while(k!=src) 53 { 54 int last = pre[k]; 55 capacity[last][k] -= increasement; //改变正向边的容量 56 capacity[k][last] += increasement; //改变反向边的容量 57 k = last; 58 } 59 sumflow += increasement; 60 } 61 return sumflow; 62 } 63 int main() 64 { 65 int i,j; 66 int start,end,ci; 67 while(cin>>n>>m) 68 { 69 memset(capacity,0,sizeof(capacity)); 70 memset(flow,0,sizeof(flow)); 71 for(i=0;i<n;++i) 72 { 73 cin>>start>>end>>ci; 74 if(start == end) //考虑起点终点相同的情况 75 continue; 76 capacity[start][end] +=ci; //此处注意可能出现多条同一起点终点的情况 77 } 78 cout<<maxFlow(1,m)<<endl; 79 } 80 return 0; 81 }
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 const int maxn = 1e3; 5 const int INF = 0x3f3f3f3f; 6 7 int n,m; //n - Vertices m - edges 8 int pre[maxn]; //record predecesor and sign if it is visited 9 int cap[maxn][maxn]; //record the capacity of residual network 10 int flow[maxn]; //record the residual flow from starting vertex to current vertex 11 queue <int> q; 12 13 int bfs(int st, int ed) 14 { 15 memset(pre,-1,sizeof(pre)); 16 while(!q.empty()) q.pop(); 17 pre[st] = 0; 18 flow[st] = INF; 19 q.push(st); 20 while(!q.empty()) 21 { 22 int t = q.front(); 23 q.pop(); 24 if(t == ed) break; 25 for(int i = 1; i <= n; i++) 26 { 27 if(pre[i] == -1 && cap[t][i] > 0) 28 { 29 pre[i] = t; 30 flow[i] = min(flow[t],cap[t][i]); 31 q.push(i); 32 } 33 } 34 } 35 if(pre[ed] == -1) return -1; 36 else return flow[ed]; 37 } 38 39 40 int EK(int st, int ed) 41 { 42 int res = 0; //the augmenting flow 43 int sum = 0; //the max_flow 44 while((res = bfs(st,ed)) != -1)//argumenting path 45 { 46 int k = ed; 47 while(k != st) 48 { 49 int f = pre[k]; 50 cap[f][k] -= res; 51 cap[k][f] += res;//reversible edge 52 k = f; 53 } 54 sum += res; 55 } 56 return sum; 57 } 58 59 60 int main() 61 { 62 int s,t,c; 63 scanf("%d%d",&n,&m); 64 memset(cap,0,sizeof(cap)); 65 for(int i = 0; i < m; i++) 66 { 67 scanf("%d%d%d",&s,&t,&c); 68 cap[s][t] = c; 69 } 70 int ans = EK(1,n); 71 printf("%d\n",ans); 72 return 0; 73 } 74 //这是第二个板子,我怕第一个错了