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\) 算法求最大流

在流网络中不考虑反向边,对于一个可行流(从源点流出的流量-流入源点的流量)来说,其必须满足两个条件:容量限制、流量守恒
在残留网络中考虑反向边,其是针对某一个可行流定义的,设 \(c\) 为原图中某条边的容量,流量为 \(f\),其正向边的容量为 \(c-f\),反向边容量为 \(f\),对于流网络的一个可行流 \(f\),对应的残留网络的一个可行流 \(f'\)(可能为负数),\(f+f'\) 是原流网络的另一个可行流
在残留网络中如果存在一条增广路径(即存在一条权值大于 \(0\) 的可行流)的话,则对应的原流网络的可行流一定不是最大流(最大可行流)
割的定义:将流网络中的所有节点分为两部分,一部分包含源点 \(s\) 的集合 \(S\),另一部分包含汇点 \(t\) 的集合 \(T\),且 \(S\bigcup T=V,S\bigcap T=\varnothing\),可以知道割有 \(2^{\left | V \right |-2}\) 中,割的容量(最小割即最小容量) \(c(S,T)=\sum_{u\in S,v\in T}c(u,v)\),割的流量 \(f(S,T)=\sum_{u\in S,v\in T}f(u,v)-\sum_{u\in T,v\in S}f(u,v)\),易得 \(f(S,T)\leq c(S,T)\),而且可以证明 \(f(S,T)\) 可以对应流网络中的一个可行流
证明:很容易得到以下性质:
前提:\(X\bigcap Y=\varnothing\)

  1. \(f(X,Y)=-f(Y,X)\)
  2. \(f(X,X)=0\)
  3. \(f(Z,X\bigcup Y)=f(Z,X)+f(Z,Y)\)
  4. \(f(X\bigcup Y,Z)=f(X,Z)+f(Y,Z)\)

借此,得到下面等式:

\[f(S,T)=f(S,V)-f(S,S)\\\ =f(S,V)\\\ =f({s},V)+f(S-{s},V)\\\ =f({s},V) =\left | f \right | \]

得证
即有 \(\left | f \right |=f(S,T)\leq c(S,T)\),即有 \(最大流\leq 最小割\)

最大流最小割定理

  1. 可行流 \(f\) 是最大流

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

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

证明:
\(1\rightarrow 2\)
反证法:假设如果 \(f\) 是最大流,但 \(f\) 的残留网络中存在增广路,即残留网络中存在一个可行流 \(\left | f' \right |>0\),则由性质,\(f+f'\) 也是原流网络的一个可行流,且该权值比最大流还大,矛盾,故 \(1\rightarrow 2\)
\(3\rightarrow 1\)
\(|f| = c(S, T)\),则 \(最大流\leq c(S,T)=|f|\),则 \(f=最大流\)
\(2\rightarrow 3\)
构造:令 \(S=在残留网络中,从 s 出发沿容量大于 0 的边走所遍历到的点且不含 t\)\(T=V-S\),则有 \(u\in S,v\in T,f(u,v)=c(u,v)\),假设 \(f(u,v)<c(u,v)\),则在残留网路中一定会有 \(u\) 连向 \(v\) 且权值为正的容量,则 \(v\) 应该也属于 \(S\),矛盾,即 \(u\in S,v\in T,f(u,v)=c(u,v)\),同理, \(u\in T,v\in S,f(u,v)=0\),则 \(|f|=f(S,T)=c(S,T)\)

上面三个条件知一可得其二,且由 \(3\) 可以得到一个结论:\(最大流=最小割\)

\(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;
}
posted @ 2022-08-03 16:29  zyy2001  阅读(43)  评论(0编辑  收藏  举报