算法简介:(复杂度 最坏O(VE^2) )
不断寻找(bfs) 源点s 和 汇点t 之间的增广路,不断更新s流出量的值 以及 这条路上的 残余网络值,直到找不到增广路。
此时,s流出量的值达到最大,故称之最大流。
增广路:(不同于二分匹配那个)
这条路从源点开始一直一段一段的连到了汇点,并且,这条路上的每一段都满足流量<容量(即 可增广)。
详见:
http://www.wutianqi.com/?p=3107
代码实现:
1 #define MAXN 205 2 #define INF 0x3f3f3f3f 3 using namespace std; 4 5 int n, m; 6 int r[MAXN][MAXN]; // 残余网络 7 int pre[MAXN]; //前继节点, 用于增广路上的回溯。 8 bool vis[MAXN]; //visit 9 10 bool bfs(int s, int t) 11 { 12 queue <int> q; 13 memset(vis, 0, sizeof(vis)); 14 pre[s] = s; 15 vis[s] = 1; 16 q.push(s); 17 while(!q.empty()){ 18 int p = q.front(); 19 q.pop(); 20 for(int i=1; i<=n; i++) 21 if(r[p][i]>0 && !vis[i]){ 22 pre[i] = p; 23 vis[i] = 1; 24 if(i == t) //找到增广路 25 return true; 26 q.push(i); 27 } 28 } 29 return false; 30 } 31 32 int EK(int s, int t) 33 { 34 int ans = 0, d; 35 //d: 增广路上的最小值,即最大可增广值。 36 while(bfs(s, t)){ 37 d = INF; 38 for(int i=t; i!=pre[i]; i=pre[i]) 39 d = min(d, r[pre[i]][i]); 40 for(int i=t; i!=pre[i]; i=pre[i]){ 41 r[pre[i]][i] -= d; //更新增广路 42 r[i][pre[i]] += d; //更新反向边 43 } 44 ans += d; 45 } 46 return ans; 47 }
可A模版题——hdu 1532(注意有重边!)
http://acm.hdu.edu.cn/showproblem.php?pid=1532
可A二分匹配——hdu 2063
用最大流做做看把。(数据水,不会超时)