【模板】网络最大流
题目描述
如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。
输入输出格式
输入格式:
第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来M行每行包含三个正整数ui、vi、wi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi)
输出格式:
一行,包含一个正整数,即为该网络的最大流。
输入输出样例
输入样例#1:
4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40
输出样例#1:
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。
.
.
.
.
.
程序:
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int ls[100001],dis[100001];
int n,m,s,t,cnt,ans,x,y,w;
queue<int> q;
struct edge
{
int y,w,op,next;
}a[500000];
void add(int x,int y,int w)
{
a[++cnt]=(edge){y,w,cnt+1,ls[x]};
ls[x]=cnt;
a[++cnt]=(edge){x,0,cnt-1,ls[y]};
ls[y]=cnt;
}
bool bfs()
{
while (!q.empty()) q.pop();
for (int i=1;i<=n;i++)
dis[i]=2147483647;
dis[s]=0;
q.push(s);
while (!q.empty())
{
int x=q.front();
q.pop();
for (int i=ls[x];i>0;i=a[i].next)
{
int y=a[i].y;
if ((a[i].w)&&(dis[y]>dis[x]+1))
{
dis[y]=dis[x]+1;
if (y==t) return 1;
q.push(y);
}
}
}
return 0;
}
int dfs(int x,int q)
{
if (x==t) return q;
int sum=0;
for (int i=ls[x];i>0;i=a[i].next)
{
int y=a[i].y;
if ((a[i].w)&&(dis[y]==dis[x]+1))
{
int f=dfs(y,min(a[i].w,q-sum));
if (!f) dis[y]=-1;
a[i].w-=f;
a[a[i].op].w+=f;
sum+=f;
if (sum==q) break;
}
}
return sum;
}
int dinic()
{
int ans=0;
while (bfs()) ans+=dfs(s,2147483647);
return ans;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&w);
add(x,y,w);
}
ans=dinic();
printf("%d",ans);
}