1.什么是网络流?
类比一张水域网络,每条河流都有限定最大流过的水流,现在我们要找从水源到终点最多可以流多少水。水源叫做源点,而终点叫做汇点。
2.什么是增广路?
我们从A点可以流20mol水到B点,但是如果只流了14mol,从A到B的增广路就是6mol,也就是还能流6mol水到B点。当然,为了方便后悔,我们再弄一条从B到A的增广路,流量是14mol,意味着我们可以撤走这14mol的水。
3.最大流问题的做法?
常用的算法是增广路算法,就是每次都找一条增广路,然后把增广路上的流量都增加(或者容量都减少),注意反向边要进行逆操作。这样这样,找到到不了汇点时,我们就已经充分利用了每一条路,这样就得到了最大流。而找增广路的过程,用dfs和bfs都是可以的,我用的是bfs。
4.代码
题目:HDU3549
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<queue>
#include<climits>
using namespace std;
int flow[17][17];
int fa[17],liu[17],que[201];
int n,m,T;
int bfs(){
int i,j,head=1,tail=1,from;
que[1]=1;liu[1]=INT_MAX;
memset(fa,0,sizeof(fa));
while(head<=tail){
from=que[head];
if(from==n)break;
for(i=1;i<=n;i++){
if(flow[from][i]>0&&fa[i]==0){
liu[i]=min(liu[from],flow[from][i]);
fa[i]=from;
tail++;que[tail]=i;
}
}
head++;
}
if(fa[n]==0)return -1;
return liu[n];
}
int find(){
int ans=0,x,kl,last;
kl=bfs();
while(kl!=-1){
ans+=kl;
x=n;
while(x!=1){
last=fa[x];
flow[last][x]-=kl;flow[x][last]+=kl;
x=last;
}
kl=bfs();
}
return ans;
}
int main()
{
int i,j,x,y,z,cnt=0;
scanf("%d",&T);
while(T){
memset(flow,0,sizeof(flow));
T--;cnt++;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
flow[x][y]+=z;
}
printf("Case %d: %d\n",cnt,find());
}
return 0;
}
题目:HDU1532
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<queue>
#include<climits>
using namespace std;
int n,m;
int flow[202][202];//注意重边!
int fa[202],liu[202],que[1002];//fa:上一点,liu:从上一点流过来的流量
int bfs(){
int i,j,head=1,tail=1,from,to;
que[1]=1;liu[1]=INT_MAX;
memset(fa,0,sizeof(fa));
while(head<=tail){
from=que[head];
if(from==n)break;
for(i=1;i<=n;i++){
if(i!=from&&flow[from][i]>0&&fa[i]==0){//用fa来堵路
liu[i]=min(liu[from],flow[from][i]);
fa[i]=from;
tail++;que[tail]=i;
}
}
head++;
}
if(fa[n]==0)return -1;
return liu[n];
}
int find(){
int ans=0,kl,x,last,cnt=0;
kl=bfs();
while(kl!=-1){
ans+=kl;x=n;
while(x!=1){//减少容量,等于增加流量
last=fa[x];
flow[last][x]-=kl;flow[x][last]+=kl;
x=last;
}
kl=bfs();
}
return ans;
}
int main()
{
int i,j,x,y,z;
while(scanf("%d%d",&m,&n)==2){
memset(flow,0,sizeof(flow));
for(i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
flow[x][y]+=z;//不用定义相反边,因为相反边是用来后悔的,注意重边
}
printf("%d\n",find());
}
return 0;
}