题目链接:排水沟
题意:现有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 ", bfs(1, m)); 55 } 56 return 0; 57 }
【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 ", dinic()); 70 } 71 return 0; 72 }