题目链接:
http://poj.org/problem?id=1273
解题思路:
题目大意:
给你有m个池塘(从1到m开始编号,1为源点,m为汇点)及n条水渠,然后给你这n条水渠所连接的池塘和所能流过的水量,求水渠中所
能流过的水的最大容量。
算法思想:
最大流模板题。。。
AC代码(增广路算法Edmonds_Karp):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 201;
const int INF = 0x3f3f3f3f;
int n,m;
int flow[N][N],cap[N][N],a[N],p[N];
//分别为:flow[u][v]为<u,v>流量、cap[u][v]为<u,v>容量、a[i]表示源点s到节点i的路径上的最小残留量、p[i]记录i的前驱
void Edmonds_Karp(){
int s = 1;//从1开始
int sum = 0;//记录最大流量
queue<int>q;//队列,用bfs找增广路
while(1){
memset(a,0,sizeof(a));//每找一次,初始化一次
a[s] = INF;
q.push(s);//源点入队
while(!q.empty()){
int u = q.front();
q.pop();
for(int v = 1; v <= m; v++){
if(!a[v] && flow[u][v]<cap[u][v]){
p[v] = u;
q.push(v);
a[v] = min(a[u],cap[u][v]-flow[u][v]);//s-v路径上的最小残量
}
}
}
if(a[m] == 0)//找不到增广路,则当前流已经是最大流
break;
sum += a[m];//流加上
for(int i = m; i != s; i = p[i]){// //从汇点顺着这条增广路往回走
flow[p[i]][i] += a[m];//更新正向流量
flow[i][p[i]] -= a[m];//更新反向流量
}
}
printf("%d\n",sum);
}
int main(){
while(~scanf("%d%d",&n,&m)){
int v,u,w;
memset(flow,0,sizeof(flow));//初始化
memset(cap,0,sizeof(cap));
while(n--){
scanf("%d%d%d",&u,&v,&w);
cap[u][v] += w;//注意图中可能出现相同的边
}
Edmonds_Karp();
}
return 0;
}
AC代码(空间优化Edmonds_Karp):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 201;
const int INF = 0x3f3f3f3f;
int n,m;
int cap[N][N],a[N],p[N];
void Edmonds_Karp(){
int s = 1;//从1开始
int sum = 0;//记录最大流量
queue<int>q;//队列,用bfs找增广路
while(1){
memset(a,0,sizeof(a));//每找一次,初始化一次
a[s] = INF;
q.push(s);//源点入队
while(!q.empty()){
int u = q.front();
q.pop();
for(int v = 1; v <= m; v++){
if(!a[v] && cap[u][v]>0){
p[v] = u;
q.push(v);
a[v] = min(a[u],cap[u][v]);//s-v路径上的最小残量
}
}
}
if(a[m] == 0)//找不到增广路,则当前流已经是最大流
break;
sum += a[m];//流加上
for(int i = m; i != s; i = p[i]){// //从汇点顺着这条增广路往回走
cap[p[i]][i] -= a[m];//更新正向流量
cap[i][p[i]] += a[m];//更新反向流量
}
}
printf("%d\n",sum);
}
int main(){
while(~scanf("%d%d",&n,&m)){
memset(cap,0,sizeof(cap));//初始化
int u,v,w;
while(n--){
scanf("%d%d%d",&u,&v,&w);
cap[u][v] += w;//注意图中可能出现相同的边
}
Edmonds_Karp();
}
return 0;
}
AC代码(Dinic):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 210;
const int INF = 0x3f3f3f3f;
struct edge{
int st,ed;
int c;
int next;
}edge[maxn<<1];
int n,m;
int s,t;
int e,head[maxn],d[maxn];
void init(){
int a,b,c;
s = 1;t = m;e = 0;
memset(head,-1,sizeof(head));
for(int i = 1; i <= n; i++){
scanf("%d%d%d",&a,&b,&c);
edge[e].st = a;edge[e].ed = b;edge[e].c = c;
edge[e].next = head[a];head[a] = e++;
edge[e].st = b;edge[e].ed = a;edge[e].next = head[b];
head[b]=e++;
}
}
int bfs(){
memset(d,-1,sizeof(d));
queue<int> q;
d[s] = 0;
q.push(s);
int cur;
while(!q.empty()){
cur = q.front();
q.pop();
for(int i=head[cur]; i != -1; i = edge[i].next){
if(d[edge[i].ed]==-1 && edge[i].c){
d[edge[i].ed] = d[cur]+1;
q.push(edge[i].ed);
}
}
}
if(d[t] < 0)
return 0;
return 1;
}
int dinic(int x,int flow){
if(x == t)
return flow;
int a;
for(int i = head[x]; i != -1; i = edge[i].next){
if(d[edge[i].ed]==d[x]+1 && edge[i].c>0 && (a=dinic(edge[i].ed,min(flow,edge[i].c)))){
edge[i].c -= a;
edge[i^1].c += a;
return a;
}
}
return 0;
}
int main(){
while(~scanf("%d%d",&n,&m)){
int ans=0,tt;
init();
while(bfs()){
tt=dinic(1,INF);
ans += tt;
}
printf("%d\n",ans);
}
return 0;
}