网络流——poj1273(入门)

题目链接:排水沟

题意:现有n个排水沟和m个点(其中1是源点,m是汇点),给定n个排水沟所连接的点,求从源点到汇点的最大流量。

 

【EK解法】

 1 #include <algorithm>  
 2 #include <queue>  
 3 #include <string.h>  
 4 using namespace std;  
 5 int const MAX = 1005;  
 6 int const inf = 0x3f3f3f3f;  
 7 int c[MAX][MAX];//c[u][v]保存容量  
 8 int f[MAX][MAX];//f[u][v]保存当前流量  
 9 int a[MAX];// a数组在每趟bfs中找到最小路径中最小残余流量的,a数组使个递推数组,a[v]的意思是从源点s到点v的最小残余流量  
10 int p[MAX];//保存前一个点  
11 int n, m;  
12 int bfs(int s, int t)  
13 {  
14     queue<int> q;  
15     int flow = 0;  
16     while(!q.empty())   q.pop();  
17     memset(f, 0, sizeof(f));  
18     while(1){  
19         memset(a, 0, sizeof(a));  
20         a[s] = inf;//将起始点的最小残余量设为最大  
21         q.push(s);  
22         while(!q.empty()){//bfs找到一条最短路,这里的边不代表距离,可以看作每两个点都是单位距离的  
23             int u;  
24             u = q.front();  
25             q.pop();  
26             for(int v = 1; v <= m; v++){//枚举所有点v <u,v>  
27                 if(!a[v] && c[u][v] > f[u][v]){//a[]可以代替vis[],来判断这个点是否已经遍历过,后面那个条件更是起了关键作用,很巧妙  
28                     p[v] = u;  
29                     q.push(v);  
30                     a[v] = min(a[u], c[u][v] - f[u][v]);//递推  
31                 }  
32             }  
33         }  
34         if(!a[t])   break;//直到最小残余流量为0时,退出  
35         for(int u = t; u != s; u = p[u]){  
36             f[p[u]][u] += a[t];  
37             f[u][p[u]] -= a[t];  
38         }  
39         flow += a[t];  
40     }  
41     return flow;  
42 }  
43   
44 int main()  
45 {  
46     while(~scanf("%d %d", &n, &m)){  
47         memset(c, 0, sizeof(c));  
48         memset(p, 0, sizeof(p));  
49         for(int i = 1; i <= n; i++){  
50             int u, v, w;  
51             scanf("%d %d %d", &u, &v, &w);  
52             c[u][v] += w;  
53         }  
54         printf("%d\n", bfs(1, m));  
55     }  
56     return 0;  
57 }
EK解法

【Dinic解法】

 1 #include <cstdio>
 2 #include <string.h>
 3 #include <queue>
 4 using namespace std;
 5 int const inf = 0x3f3f3f3f;
 6 int const MAX = 205;
 7 int n, m;
 8 int c[MAX][MAX], dep[MAX];//dep[MAX]代表当前层数
 9 
10 int bfs(int s, int t)//重新建图,按层次建图
11 {
12     queue<int> q;
13     while(!q.empty())
14         q.pop();
15     memset(dep, -1, sizeof(dep));
16     dep[s] = 0;
17     q.push(s);
18     while(!q.empty()){
19         int u = q.front();
20         q.pop();
21         for(int v = 1; v <= m; v++){
22             if(c[u][v] > 0 && dep[v] == -1){//如果可以到达且还没有访问,可以到达的条件是剩余容量大于0,没有访问的条件是当前层数还未知
23                 dep[v] = dep[u] + 1;
24                 q.push(v);
25             }
26         }
27     }
28     return dep[t] != -1;
29 }
30 
31 int dfs(int u, int mi, int t)//查找路径上的最小流量
32 {
33     if(u == t)
34         return mi;
35     int tmp;
36     for(int v = 1; v <= m; v++){
37         if(c[u][v] > 0 && dep[v] == dep[u] + 1  && (tmp = dfs(v, min(mi, c[u][v]), t))){
38             c[u][v] -= tmp;
39             c[v][u] += tmp;
40             return tmp;
41         }
42     }
43     return 0;
44 }
45 
46 int dinic()
47 {
48     int ans = 0, tmp;
49     while(bfs(1, m)){
50         while(1){
51             tmp = dfs(1, inf, m);
52             if(tmp == 0)
53                 break;
54             ans += tmp;
55         }
56     }
57     return ans;
58 }
59 
60 int main()
61 {
62     while(~scanf("%d %d", &n, &m)){
63         memset(c, 0, sizeof(c));
64         int u, v, w;
65         while(n--){
66             scanf("%d %d %d", &u, &v, &w);
67             c[u][v] += w;
68         }
69         printf("%d\n", dinic());
70     }
71     return 0;
72 }
Dinic解法

 

posted @ 2017-08-12 11:12  GGBeng  阅读(260)  评论(0编辑  收藏  举报