题意:一个人修了一个水渠(有向连通图),每条边有能通过的最大流量,问从起点到终点,最多能运输多少水。
解法:最大流问题。最大流的入门题,也是我做的第一个最大流题目,阅读了刘汝佳的小白和kuangbin大神的博客……
使用的是Edmonds-Karp算法,用bfs搜索一条路,记录这条路的路径和通过的最大流量,更新残余网络,再bfs下一条路径,直到搜不到一条路径为止。
搜索路径的时候要关注已通过流量是否达到最大流量,如果达到则不能走这条路,并记录此路径本次搜索能通过的最大流量,由于这个标记一定不为0,所以可以当作visit数组。
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string> #include<string.h> #include<math.h> #include<limits.h> #include<time.h> #include<stdlib.h> #include<map> #include<queue> #include<set> #include<stack> #include<vector> #define LL long long using namespace std; int main() { int cap[205][205];//邻接矩阵,每个边能通过的最大流量 int n, m; while(~scanf("%d%d", &n, &m)) { memset(cap, 0, sizeof(cap)); for(int i = 0; i < n; i++) { int u, v, f; scanf("%d%d%d", &u, &v, &f); cap[u][v] += f;//输入会出现重复边,值需要累加(被坑了好久) } int a[205], p[205], flow[205][205];//a记录一条路径中每个点通过的最大流量 p记录路径 flow邻接矩阵,记录残余网络 memset(flow, 0, sizeof(flow)); int ans = 0; while(1) { queue <int> q; memset(a, 0, sizeof(a)); a[1] = INT_MAX; q.push(1); while(!q.empty())//bfs { int u = q.front(); q.pop(); bool flag = false; for(int v = 1; v <= m; v++) { if(!a[v] && (cap[u][v] > flow[u][v])) { q.push(v); a[v] = min(a[u], cap[u][v] - flow[u][v]); p[v] = u; if(v == m) { flag = true; break; } } } if(flag)//搜索到终点后结束 break; } if(!a[m])//如果搜不到终点,说明已经是最大流 break; ans += a[m]; for(int i = m; i != 1; i = p[i])//更新残余网络 { flow[p[i]][i] += a[m]; flow[i][p[i]] -= a[m]; } } printf("%d ", ans); } return 0; }