题目来源:
https://www.luogu.org/problemnew/show/P3376
题目描述:
题目描述
如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。
输入输出格式
输入格式:
第一行包含四个正整数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。
解题思路:
模板题,我是用dinic来做,用邻接表存边,加了一点优化。。。。
代码:
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <iomanip>
#define ll long long
#define inf 1e9
const int maxn=10005;
using namespace std;
struct newt{
int to,next;ll val;
}edge[30*maxn];
int head[maxn],cur[maxn],deep[maxn],n,m,S,T,cnt;
inline void addedge(int u,int v,ll w)
{
edge[cnt].val=w;
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
inline bool bfs()
{
memset(deep,-1,sizeof(deep));
queue<int>q;
q.push(S);deep[S]=0;
for(int i=1;i<=n;i++)cur[i]=head[i];
while(!q.empty())
{
int now=q.front();q.pop();
for(int i=head[now];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(deep[v]==-1&&edge[i].val>0)deep[v]=deep[now]+1,q.push(v);
}
}
return deep[T]!=-1;
}
inline ll dfs(int u,ll op)
{
if(u==T||op==0)return op;
ll flow=0,used=0;
for(int i=cur[u];i!=-1;i=edge[i].next){
cur[u]=i;
int v=edge[i].to;
if(deep[v]==deep[u]+1&&edge[i].val>0){
used=dfs(v,min(op,edge[i].val));
if(!used)continue;
flow+=used;op-=used;
edge[i].val-=used;edge[i^1].val+=used;
if(!op)break;
}
}
if(!flow)deep[u]=-1;
return flow;
}
int main()
{
ios::sync_with_stdio(false);
memset(head,-1,sizeof(head));
cin>>n>>m>>S>>T;
cnt=0;
ll ans=0;
for(int i=1;i<=m;i++)
{
int a,b;ll c;
cin>>a>>b>>c;
addedge(a,b,c);
addedge(b,a,0);
}
while(bfs()){
ans+=dfs(S,inf);
}
cout<<ans<<endl;
return 0;
}