Java教程

2171. EK求最大流

本文主要是介绍2171. EK求最大流,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

题目链接

2171. EK求最大流

给定一个包含 \(n\) 个点 \(m\) 条边的有向图,并给定每条边的容量,边的容量非负。

图中可能存在重边和自环。求从点 \(S\) 到点 \(T\) 的最大流。

输入格式

第一行包含四个整数 \(n,m,S,T\)。

接下来 \(m\) 行,每行三个整数 \(u,v,c\),表示从点 \(u\) 到点 \(v\) 存在一条有向边,容量为 \(c\)。

点的编号从 \(1\) 到 \(n\)。

输出格式

输出点 \(S\) 到点 \(T\) 的最大流。

如果从点 \(S\) 无法到达点 \(T\) 则输出 \(0\)。

数据范围

\(2 \le n \le 1000\),
\(1 \le m \le 10000\),
\(0 \le c \le 10000\),
\(S \neq T\)

输入样例:

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

解题思路

网络流、\(EK\) 算法求最大流

模板题
最大流最小割定理

  • 可行流 \(f\) 是最大流

  • 可行流 \(f\) 的残留网络中不存在增广路

  • 存在某个割 \([S, T],|f| = c(S, T)\)

上面三个条件知一可得其二

\(EK\) 算法正是利用第二个条件得第一个条件,利用 \(bfs\) 不断得到一条增广路径,将最小的残余流量加入到最大流中,同时更新该增广路径,再次判断是否存在增广路径直到没有为止

由于网络流的复杂度上界都比较松,\(EK\) 算法一般用来处理 \(10^3\sim 10^4\) 的网络模型

  • 时间复杂度:\(O(nm^2)\)

代码

// Problem: EK求最大流
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/2173/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=1005,M=20005,inf=0x3f3f3f3f;
int n,m,s,t;
int h[N],e[M],ne[M],f[M],idx,res;
int q[N],tt,hh,d[N],pre[N];
bool st[N];
void add(int a,int b,int c)
{
	e[idx]=b,f[idx]=c,ne[idx]=h[a],h[a]=idx++;
	e[idx]=a,f[idx]=0,ne[idx]=h[b],h[b]=idx++;
}
bool bfs()
{
	memset(st,0,sizeof st);
	d[s]=inf;
	q[0]=s;
	st[s]=true;
	tt=hh=0;
	while(hh<=tt)
	{
		int x=q[hh++];
		for(int i=h[x];~i;i=ne[i])
		{
			int y=e[i];
			if(!st[y]&&f[i])
			{
				st[y]=true;
				d[y]=min(d[x],f[i]);
				pre[y]=i;
				if(y==t)return true;
				q[++tt]=y;
			}
		}
	}
	return false;
}
int ek()
{
	while(bfs())
	{
		res+=d[t];
		for(int i=t;i!=s;i=e[pre[i]^1])
			f[pre[i]]-=d[t],f[pre[i]^1]+=d[t];
	}
	return res;
}
int main()
{
    memset(h,-1,sizeof h);
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++)
    {
    	int u,v,c;
    	scanf("%d%d%d",&u,&v,&c);
    	add(u,v,c);
    }
    printf("%d",ek());
    return 0;
}
这篇关于2171. EK求最大流的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!