HDU 3549 Flow Problem(最大流模版EK算法)
第一道最大流,赤裸裸的模版题,刚好可以熟悉模版用。今天看了一下最大流,就看了一个EK算法,感觉有点和二分图匹配算法有点相似,对于最大流问题有点了解了,不过为什么这么做,也不是 很懂,只是把代码给敲了一遍,以后慢慢学习。
EK算法,过程是先BFS找到str到end的一条路,然后每条路上的流量(key[][]记录)取这些路中流量的最小值(flow[]记录),在这条路上的流量都减去这个值,然后建立反向边,然后继续找增广路,直到找不到为止。有前驱的结点不会再找了,所以几遍之后肯定找不到了。
1 #include <cstdio> 2 #include <cstring> 3 #include <string> 4 #include <cmath> 5 #include <queue> 6 using namespace std; 7 #define INF 0x7fffffff 8 int key[101][101]; 9 int path[101],flow[101],n,m,str,end; 10 queue<int>que; 11 int bfs() 12 { 13 int i,t; 14 while(!que.empty()) que.pop(); 15 memset(path,-1,sizeof(path)); 16 path[str] = 0; 17 flow[str] = INF;//初始化 18 que.push(str); 19 while(!que.empty())//BFS 20 { 21 t = que.front(); 22 que.pop(); 23 if(t == end) break;//已经找到end了 24 for(i = 1;i <= n;i ++) 25 { 26 if(i != str&&key[t][i]&&path[i] == -1) 27 { 28 flow[i] = flow[t] < key[t][i] ? flow[t]:key[t][i];//记录流量 29 que.push(i); 30 path[i] = t;//记录前驱 31 } 32 } 33 } 34 if(path[end] == -1)//找不到路径时 35 return -1; 36 else 37 return flow[end]; 38 } 39 int EK() 40 { 41 int ans = 0,pre,now,step; 42 while((step = bfs()) != -1) 43 { 44 ans += step; 45 now = end; 46 while(now != str) 47 { 48 pre = path[now]; 49 key[now][pre] += step; 50 key[pre][now] -= step; 51 now = pre; 52 } 53 } 54 return ans; 55 } 56 int main() 57 { 58 int i,t,sv,ev,w,num = 0; 59 scanf("%d",&t); 60 while(t--) 61 { 62 num ++; 63 memset(key,0,sizeof(key)); 64 scanf("%d%d",&n,&m); 65 for(i = 1;i <= m;i ++) 66 { 67 scanf("%d%d%d",&sv,&ev,&w); 68 key[sv][ev] += w; 69 } 70 str = 1;end = n; 71 printf("Case %d: %d\n",num,EK()); 72 } 73 return 0; 74 }