题目描述
如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。
输入输出格式
输入格式:第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来M行每行包含三个正整数ui、vi、wi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi)
输出格式:一行,包含一个正整数,即为该网络的最大流。
输入输出样例
4 5 4 3 4 2 30 4 3 20 2 3 20 2 1 30 1 3 40
50
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=10,M<=25
对于70%的数据:N<=200,M<=1000
对于100%的数据:N<=10000,M<=100000
样例说明:
题目中存在3条路径:
4-->2-->3,该路线可通过20的流量
4-->3,可通过20的流量
4-->2-->1-->3,可通过10的流量(边4-->2之前已经耗费了20的流量)
故流量总计20+20+10=50。输出50。
using namespace std;
int del[N*20],pos[N*20],pre[N];
int fir[N],ne[N*20],val[N*20],to[N*20],flow[N*20],a[N*20],from[N*20];
int m,n,s,t,u,v,w,tot,dnum;
void add(int uu,int vv,int ww){ from[++tot]=uu;to[tot]=vv;val[tot]=ww;ne[tot]=fir[uu];fir[uu]=tot;flow[tot]=0;}
int BFS(int st,int en){
queue<int> q;
PER(i,1,n) a[i]=0;
a[st]=INF;pre[st]=0;
q.push(st);
while(!q.empty())
{
int index=q.front();
q.pop();
forw(i,index)
{
if(val[i]>flow[i]&&!a[to[i]])
{
a[to[i]]=min(a[index],val[i]-flow[i]);
pre[to[i]]=i;
q.push(to[i]);
}
}
if(a[en]) break;
}
if(!a[en]) return 0;
for(int i=en;i!=st;i=from[pre[i]])
{
val[(pre[i]-1)^1+1]-=a[en];
flow[pre[i]]+=a[en];
}
return a[en];}
int maxflow
(int st,int en){
int inc=1,fl=0;
while(inc) {
inc=BFS(st,en);
fl+=inc;
}
return fl;}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&t);
PER(i,1,m)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);add(v,u,0);
}
cout<<maxflow(s,t)<<endl;}
本题的思路:就是把一条流去掉后,连等量的反向边,这样做就可以跑回来实现反悔。
具体实现用BFS一直寻找增广路。