题目链接:排水沟

题意:现有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解法

相关文章: