题目大意:
给出一个网络图,以及其源点和汇点,求出其网络最大流。
4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40
50
思路:
最大流模板题。
个人比较喜欢用(因为它好理解编码难度低)
推荐一篇网络流好文章
网络流想必大家都知道。可以很轻松的跑过此题所以不用Dinic。
此题与 洛谷 草地排水 基本一样(只要改输入),所以就不再单独写博客。
代码:
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#define Inf 999999999
using namespace std;
int n,m,s,t,k,x,y,z,sum,minn,head[20001];
bool vis[20001];
struct edge //邻接表
{
int c,next,to; //c是总流量
}e[200001];
struct way //记录路径
{
int v,e; //表示上一个节点和这条路流量
}w[200001];
void add(int from,int to,int c) //建图
{
k++;
e[k].c=c;
e[k].to=to;
e[k].next=head[from];
head[from]=k;
}
bool bfs()
{
queue<int> q;
memset(vis,0,sizeof(vis));
memset(w,-1,sizeof(w));
q.push(s);
vis[s]=1;
while (q.size())
{
int u=q.front();
q.pop();
for (int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if (vis[v]||!e[i].c) continue; //到达了这个点或这条边没流量了就不走
w[v].v=u;
w[v].e=i; //记录路径
if (v==t) return true; //到达终点
q.push(v);
vis[v]=1;
}
}
return false;
}
int main()
{
k=1;
scanf("%d%d%d%d",&n,&m,&s,&t);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,0);
}
while (bfs()) //EK
{
minn=Inf;
for (int i=t;i!=s;i=w[i].v)
minn=min(minn,e[w[i].e].c); //最小流量
for (int i=t;i!=s;i=w[i].v)
{
e[w[i].e].c-=minn; //正向边
e[w[i].e^1].c+=minn; //反向边
}
sum+=minn;
}
printf("%d\n",sum);
return 0;
}