题目描述
如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。
输入输出格式
输入格式:
第一行包含四个正整数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。
题解:网络流EK算法模板。
#include <cstdio>
#include <queue>
#include <cstring>
#define N 100005
int n,m,s,t,cnt,ans,first[10005],pre[10005];
bool vis[10005];
struct bb{
int fr,to,va,nxt;
}E[N*2];
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
if (ch=='-')
{
f=-1;
ch=getchar();
}
while ((ch<'0')||(ch>'9')) ch=getchar();
while ((ch>='0')&&(ch<='9'))
{
x=x*10+ch-48;
ch=getchar();
}
return f*x;
}
inline void add(int x,int y,int z)
{
E[cnt].fr=x;
E[cnt].to=y;
E[cnt].va=z;
E[cnt].nxt=first[x];
first[x]=cnt++;
E[cnt].fr=y;
E[cnt].to=x;
E[cnt].va=0;
E[cnt].nxt=first[y];
first[y]=cnt++;
}
inline bool BFS()
{
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
queue<int> q;
q.push(s);
vis[s]=1;
while (!q.empty())
{
int x=q.front();
q.pop();
for (int i=first[x];i!=-1;i=E[i].nxt)
{
int k=E[i].to;
if ((E[i].va<=0)||vis[k]) continue;
vis[k]=1;
q.push(k);
pre[k]=i;
if (k==t) return 1;
}
}
return 0;
}
inline void EK()
{
while (BFS())
{
int i=pre[t],x=0x3f3f3f3f;
while (i!=-1)
{
if (E[i].va<x) x=E[i].va;
i=pre[E[i].fr];
}
i=pre[t];
while (i!=-1)
{
E[i].va-=x;
E[i^1].va+=x;
i=pre[E[i].fr];
}
ans+=x;
}
}
int main()
{
n=read(),m=read(),s=read(),t=read();
memset(first,-1,sizeof(first));
for (int i=1;i<=m;i++)
{
int x=read(),y=read(),z=read();
add(x,y,z);
}
EK();
printf("%d\n",ans);
}