LibreOJ #101. 最大流
题目描述
这是一道模板题。
给定 n nn 个点,m mm 条边,给定每条边的容量,求从点 s ss 到点 t tt 的最大流。
输入格式
第一行四个整数 n nn、m mm、s ss、t tt。
接下来的 m mm 行,每行三个整数 u uu、v vv、c cc,表示 u uu 到 v vv,流量为 c cc 的一条边。
输出格式
输出点 s ss 到点 t tt 的最大流。
样例
样例输入
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
样例输出
14
数据范围与提示
1≤n≤106,1≤m≤4×106,0≤c≤231−1 1 \leq n \leq 10 ^ 6, 1 \leq m \leq 4 \times 10 ^ 6, 0 \leq c \leq 2 ^ {31} - 11≤n≤106,1≤m≤4×106,0≤c≤231−1
模板题,需要当前弧优化
#include <cstring> #include <vector> #include <cstdio> #include <queue> #define N 4000005 using namespace std; struct node { int to,next,dis; }edge[N*2]; int tot=1,Answer,dis[1000005],head[1000005],n,m,s,t,i,j; void add(int from,int to,int w) { tot++; edge[tot].next=head[from]; edge[tot].to=to; edge[tot].dis=w; head[from]=tot; } bool bfs() { queue<int>q; memset(dis,-1,sizeof(dis)); dis[s]=0; q.push(s); while(!q.empty() ) { int Top=q.front() ; q.pop() ; for(i=head[Top];i;i=edge[i].next) { if(dis[edge[i].to]==-1&&edge[i].dis>0) { dis[edge[i].to]=dis[Top]+1; if(edge[i].to==t) return 1; else q.push(edge[i].to); } } } return 0; } int work(int now,int f) { if(now==t||f==0) return f; int rest=0; for(int i=head[now];i;i=edge[i].next) { int v=edge[i].to; if(edge[i].dis>0&&dis[v]==dis[now]+1) { int t=work(v,min(f,edge[i].dis)); rest+=t; f-=t; edge[i].dis-=t; edge[i^1].dis+=t; if(f==0) return rest; } } if(rest!=f) dis[now]=-1; return rest; } int main() { scanf("%d%d%d%d",&n,&m,&s,&t); int u,v,l; for(i=0;i<m;++i) { scanf("%d%d%d",&u,&v,&l); add(u,v,l); add(v,u,0); } while(bfs()) Answer+=work(s,1e8); printf("%d",Answer); return 0; }
我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。