POJ 1273 Drainage Ditches
题意:一个人修了一个水渠(有向连通图),每条边有能通过的最大流量,问从起点到终点,最多能运输多少水。
解法:最大流问题。最大流的入门题,也是我做的第一个最大流题目,阅读了刘汝佳的小白和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\n", ans);
}
return 0;
}

浙公网安备 33010602011771号