题目链接:排水沟
题意:现有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 }