题目描述
给定 n 个点,m 条有向边,给定每条边的容量,求从点 s 到点 t 的最大流。
输入格式
第一行包含四个正整数n、m、s、t,用空格分隔,分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来m行每行包含三个正整数 u i 、 v i 、 c i u_i、v_i、c_i ui、vi、ci,用空格分隔,表示第iii条有向边从 u i u_i ui出发,到达 v i v_i vi,容量为 c i c_i ci
输出格式
一个整数,表示s到t的最大流
输入输出样例
输入 #1
7 14 1 7
1 2 5
1 3 6
1 4 5
2 3 2
2 5 3
3 2 2
3 4 3
3 5 3
3 6 7
4 6 5
5 6 1
6 5 1
5 7 8
6 7 7
输出 #1
14
输入 #2
10 16 1 2
1 3 2
1 4 2
5 2 2
6 2 2
3 5 1
3 6 1
4 5 1
4 6 1
1 7 2147483647
9 2 2147483647
7 8 2147483647
10 9 2147483647
8 5 2
8 6 2
3 10 2
4 10 2
输出 #2
8
说明/提示
1 ⩽ n ⩽ 1200 , 1 ⩽ m ⩽ 120000 , 1 ⩽ c ⩽ 2 31 − 1 1⩽n⩽1200,1⩽m⩽120000,1⩽c⩽2^{31}−1 1⩽n⩽1200,1⩽m⩽120000,1⩽c⩽231−1
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using std::min;
using std::vector;
using std::queue;
using std::priority_queue;
const int N=2e4+5,M=2e5+5,inf=0x3f3f3f3f;
int n,s,t,tot;
int v[M<<1],w[M<<1],first[N],next[M<<1];
int h[N],e[N],gap[N<<1],inq[N];//节点高度是可以到达2n-1的
struct cmp{
inline bool operator()(int a,int b) const{
return h[a]<h[b];//因为在优先队列中的节点高度不会改变,所以可以直接比较
}
};
queue<int> Q;
priority_queue<int,vector<int>,cmp> pQ;
inline void add_edge(int from,int to,int flow){
tot+=2;
v[tot+1]=from;v[tot]=to;w[tot]=flow;w[tot+1]=0;
next[tot]=first[from];first[from]=tot;
next[tot+1]=first[to];first[to]=tot+1;
return;
}
inline bool bfs(){
int now;
register int go;
memset(h+1,0x3f,sizeof(int)*n);
h[t]=0;Q.push(t);
while(!Q.empty()){
now=Q.front();Q.pop();
for(go=first[now];go;go=next[go]) if(w[go^1]&&h[v[go]]>h[now]+1) h[v[go]]=h[now]+1,Q.push(v[go]);
}
return h[s]!=inf;
}
inline void push(int now){
int d;
register int go;
for(go=first[now];go;go=next[go])
if(w[go]&&h[v[go]]+1==h[now]){
d=min(e[now],w[go]);
w[go]-=d;w[go^1]+=d;e[now]-=d;e[v[go]]+=d;
if(v[go]!=s&&v[go]!=t&&!inq[v[go]]) pQ.push(v[go]),inq[v[go]]=1;
if(!e[now]) break;
}
return;
}
inline void relabel(int now){
register int go;
h[now]=inf;
for(go=first[now];go;go=next[go]) if(w[go]&&h[v[go]]+1<h[now]) h[now]=h[v[go]]+1;
return;
}
inline int hlpp(){
int now,d;
register int i,go;
if(!bfs()) return 0;
h[s]=n;
memset(gap,0,sizeof(int)*(n<<1));
for(i=1;i<=n;i++) if(h[i]<inf) ++gap[h[i]];
for(go=first[s];go;go=next[go])
if(d=w[go]){
w[go]-=d;w[go^1]+=d;e[s]-=d;e[v[go]]+=d;
if(v[go]!=s&&v[go]!=t&&!inq[v[go]]) pQ.push(v[go]),inq[v[go]]=1;
}
while(!pQ.empty()){
inq[now=pQ.top()]=0;pQ.pop();push(now);
if(e[now]){
if(!--gap[h[now]]) for(i=1;i<=n;i++) if(i!=s&&i!=t&&h[i]>h[now]&&h[i]<n+1) h[i]=n+1;
relabel(now);++gap[h[now]];
pQ.push(now);inq[now]=1;
}
}
return e[t];
}
int m;
signed main(){
int u,v,w;
scanf("%d%d%d%d",&n,&m,&s,&t);
while(m--){
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
}
printf("%d\n",hlpp());
return 0;
}