题意描述:
现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条水渠,给出这n条水渠所连接的池塘和所能流过的水量,求水渠中所能流过的水的最大容量。
一道基础的最大流题目。熟悉套路。
#include<stdio.h>
#include<cstring>
#include<algorithm>
using namespace std;
int inf=0x7fffffff;
int state[100010],f[205][205],dis[205];
int n,m;
int bfs(){//构建层次图
int h, t;
memset(dis, 0xff, sizeof(dis));
state[1] = 1;
dis[1] = 0;
h = 0; t = 1;
while(h < t){
h++;
int j = state[h];
for(int i=1; i<=n; i++)
if(dis[i] < 0 && f[j][i] > 0){//未更新过,有边连接
dis[i] = dis[j] + 1;//由父节点+1 ->可以在之后的寻找中到达
t++;
state[t] = i;
}
}
if(dis[n] > 0)
return 1;
else
return 0;//走不到汇点说明没有增广路,当前答案为最大流
}
int dfs(int x, int low){
int a = 0;
if(x == n) //到达->找到最短路
return low;//从源点到x能够增加的最大流量
for(int i=1; i<=n; i++)
if(f[x][i] > 0 && dis[i] == dis[x] + 1 && (a = dfs(i, min(low, f[x][i])))){//一直递归直到找到汇点,得到增广路大小
f[x][i] -= a;//回归时处理增广路上的限流
f[i][x] += a;//正向路可通过限度减少,反向路增加
return a;
}
return 0;
}
int main(){
while(scanf("%d%d", &m, &n) != EOF){
memset(f,0,sizeof(f));
for(int i=1; i<=m; i++){
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
f[u][v] += w;
}
int ans = 0;
while( bfs() ){
int tans = 0;//可增加流量
while(tans = dfs(1, inf))
ans += tans;
}
printf("%d\n", ans);
}
return 0;
}