题目描述
如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。
输入格式
第一行包含四个正整数 n,m,s,tn,m,s,t,分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来 mm 行每行包含三个正整数 u_i,v_i,w_iui,vi,wi,表示第 ii 条有向边从 u_iui 出发,到达 v_ivi,边权为 w_iwi(即该边最大流量为 w_iwi)。
输出格式
一行,包含一个正整数,即为该网络的最大流。
输入输出样例
4 5 4 3 4 2 30 4 3 20 2 3 20 2 1 30 1 3 40
50
说明/提示
样例输入输出 1 解释
题目中存在 33 条路径:
- 4\to 2\to 34→2→3,该路线可通过 2020 的流量。
- 4\to 34→3,可通过 2020 的流量。
- 4\to 2\to 1\to 34→2→1→3,可通过 1010 的流量(边 4\to 24→2 之前已经耗费了 2020 的流量)。
故流量总计 20+20+10=5020+20+10=50。输出 5050。
数据规模与约定
- 对于 30\%30% 的数据,保证 n\leq10n≤10,m\leq25m≤25。
- 对于 100\%100% 的数据,保证 1 \leq n\leq2001≤n≤200,1 \leq m\leq 50001≤m≤5000,0 \leq w\lt 2^{31}0≤w<231。
题解:
写的dinic的板子。主要是用bfs搞出分层图,每跑一次最大流更新剩余流量即可。
用了蓝书上的trick,从1开始前向星建边,每次来回建两条,这样更新反向流量时^1即可。
/*keep on going and never give up*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define MAX 0x3f3f3f3f
#define fast std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int maxn=2e5+10;
int head[maxn],d[maxn];
int s,n,m,tot,t,mflow;
struct node{
int to,nxt,w;
}e[maxn];
void add(int x,int y,int z){
e[++tot].to=y,e[tot].w=z,e[tot].nxt=head[x],head[x]=tot;
e[++tot].to=x,e[tot].w=0,e[tot].nxt=head[y],head[y]=tot;
}
queue<int>q;
bool bfs(){
memset(d,0,sizeof(d));
while(!q.empty())q.pop();
q.push(s);d[s]=1;
while(!q.empty()){
int now=q.front();q.pop();
for(int i=head[now];i;i=e[i].nxt){
if(e[i].w&&!d[e[i].to]){
q.push(e[i].to);
d[e[i].to]=d[now]+1;
if(e[i].to==t) return 1;
}
}
}
return 0;
}
int dinic(int now,int flow){
if(now==t) return flow;
int res=flow,k;
for(int i=head[now];i&&res;i=e[i].nxt){
if(e[i].w&&d[e[i].to]==d[now]+1){
k=dinic(e[i].to,min(e[i].w,res));
if(!k) d[e[i].to]=0;
e[i].w-=k;
e[i^1].w+=k;
res-=k;
}
}
return flow-res;
}
signed main(){
fast
cin>>n>>m>>s>>t;
tot=1;
for(int i=1;i<=m;i++){
int x,y,z;cin>>x>>y>>z;
add(x,y,z);
}
int flow=0;
while(bfs()){
while(flow=dinic(s,MAX)) mflow+=flow;
}
cout<<mflow;
}