$Edmonds-Karp$[网络流]
\(原题戳这里\)

>最大流最小割定理$(Maximum Flow, Minimum Cut Theorem): $
网络的最大流等于最小割
具体的证明分三部分
1.任意一个流都小于等于任意一个割 这个很好理解 自来水公司随便给你家通点水 构成一个流 恐怖分子随便砍几刀 砍出一个割 由于容量限制 每一根的被砍的水管子流出的水流量都小于管子的容量 每一根被砍的水管的水本来都要到你家的 现在流到外面 加起来得到的流量还是等于原来的流 管子的容量加起来就是割 所以流小于等于割 由于上面的流和割都是任意构造的 所以任意一个流小于任意一个割
2.构造出一个流等于一个割 当达到最大流时 根据增广路定理 残留网络中s到t已经没有通路了 否则还能继续增广 我们把s能到的的点集设为S 不能到的点集为T 构造出一个割集\(C[S,T] S\)到T的边必然满流 否则就能继续增广 这些满流边的流量和就是当前的流即最大流
把这些满流边作为割 就构造出了一个和最大流相等的割
3.最大流等于最小割 设相等的流和割分别为Fm和Cm 则因为任意一个流小于等于任意一个割 任意\(F≤Fm=Cm≤任意C\) 定理说明完成,证明如下: 对于一个网络流图\(G=(V,E)\),其中有源点s和汇点t,那么下面三个条件是等价的:
- 流f是图G的最大流
- 残留网络Gf不存在增广路
- 对于G的某一个割\((S,T)\),此时\(f = C(S,T)\) 首先证明\(1 => 2\):
我们利用反证法,假设流f是图G的最大流,但是残留网络中还存在有增广路\(p\),其流量为\(fp\)。则我们有流\(f’=f+fp>f\)。这与\(f\)是最大流产生矛盾。
接着证明\(2 => 3\):
假设残留网络\(Gf\)不存在增广路,所以在残留网络\(Gf\)中不存在路径从s到达t。我们定义S集合为:当前残留网络中s能够到达的点。同时定义\(T=V-S\)。
此时\((S,T)\)构成一个割\((S,T)\)。且对于任意的\(u∈S,v∈T\),有\(f(u,v)=c(u,v)\)。若\(f(u,v) < c(u,v)\),则有\(Gf(u,v) > 0\),s可以到达v,与v属于T矛盾。
因此有\(f(S,T)=Σf(u,v)=Σc(u,v)=C(S,T)\)。 最后证明\(3 => 1\):
由于f的上界为最小割,当f到达割的容量时,显然就已经到达最大值,因此f为最大流。 这样就说明了为什么找不到增广路时,所求得的一定是最大流。
源点:只有流出去的点
汇点:只有流进来的点
流量:一条边上流过的流量
容量:一条边上可供流过的最大流量
残量:一条边上的容量-流量
EK时间复杂度:\(O(n m^2)\)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL ;
inline LL In() { LL res(0),f(1); register char c = getchar() ;
while(!isdigit(c)) { if(c == '-') f = -1 ; c = getchar() ; }
while(isdigit(c)) res = (res << 1) + (res << 3) + (c & 15) , c = getchar() ; return res * f ;
}
const int INF = 0x3f3f3f3f ;
const int N = 1000000 + 5 ;
int n , m , s , t ;
int cnt = 1 ;
int cost[N] ;
int from[N] ; int to[N] ; int nxt[N] ; int head[N] ;
int dis[N] ; int vis[N] ;
int flow[N] ; int last[N] ;
int maxflow ;
queue <int> q ;
inline void Add(int x,int y,int z) {
cost[++cnt] = z ;
from[cnt] = x ;
to[cnt] = y ;
nxt[cnt] = head[x] ;
head[x] = cnt ;
}
inline bool bfs(int s,int y) {
for(register int i = 1 ; i <= n ; i ++) last[i] = 0 , vis[i] = -1 ;
q.push(s) , dis[s] = 0 , vis[s] = 1 , flow[s] = INF ;
while(!q.empty()) {
int u = q.front() ;
q.pop() ;
vis[u] = 0 ;
for(register int i = head[u] ; i != -1 ; i = nxt[i]) {
int v = to[i];
if(cost[i] and vis[v] == -1) {
flow[v] = min (flow[u] , cost[i]) ;
last[v] = i ; q.push(v) ; vis[v] = u ;
}
}
}
if(vis[t] != -1) return 1;
return 0 ;
}
inline void update(int s,int t) {
int now = t ;
while(now != s) {
int i = last[now] ;
cost[i] -= flow[t] ;
cost[i^1] += flow[t] ;
now = from[i] ;
}
maxflow += flow[t] ;
}
inline void EK() {
maxflow = 0 ;
while(bfs(s,t) == 1) update(s,t) ;
}
signed main() {
n = In() ; m = In() ;
s = In() ; t = In() ;
memset(head,-1,sizeof(head)) ;
for(register int i = 1 ; i <= m ; i ++) {
int x = In() ;
int y = In() ;
int z = In() ;
Add(x,y,z) ; Add(y,x,0) ;
}
EK() ;
cout << maxflow << endl ;
return 0;
}
随机推荐
- pcre7.0在vc6.0编译
(0)从http://gnuwin32.sourceforge.net/packages/pcre.htm (pcre windows)下下载最新的windows平台源代码pcre-7.0-src. ...
- Excel小tips - 如何实现多列成绩统一排名
本文参考:http://mp.weixin.qq.com/s/XR49hyG9Cods7rOcsM-tRg 如果有以下数据文件,需要进行成绩排名. 第一步:先在成绩列后边添加一列,用来显示名次.如下: ...
- SQL 视图(Views)
SQL 视图(Views) 视图是可视化的表. 本章讲解如何创建.更新和删除视图. SQL CREATE VIEW 语句 在 SQL 中,视图是基于 SQL 语句的结果集的可视化的表. 视图包含行和列 ...
- SQL2012 尝试读取或写入受保护的内存。这通常指示其它内存已损坏
今天打开SQL2012,突然就连接不了数据库.一開始还以为是某个server崩溃了.结果试了好几个.都还是如此,弹出提演示样例如以下: 尝试读取或写入受保护的内存.这通常仅仅是其它内存已损坏.(Sys ...
- POJ 2545+2591+2247+1338简单水题
[题意简述]:就是有这种一个序列.就拿当p1 = 2,p2 = 3, p3 = 5,来举例.由这三个数为基准组成的序列是: 2,3,4,5,6,8,9,10,12--如今给你这个序列数组的下标,让你求 ...
- I2C上拉电阻取值范围
I2C总线是微电子通信控制领域中常用的一种总线标准,具备接线少,控制简单,速率高等优点.在I2C电路中常见的上拉电阻有1k.1.5k.2.2k.4.7k.5.1k.10k等等,但是应该如何根据开发要求 ...
- iOS与HTML交互问题
一. 加载后台传过来的HTML标签,文字都能正常显示但是图片显示不了.找问题找了很久没有发现那个地方写错,也问了别人都不知道,后来问了Android才知道,后台传过来的HTML标签,有些是转义过的.移 ...
- Bean Query 第一个版本号(1.0.0)已公布
BeanQuery 是一个把对象转换为Map的Java工具库. 支持选择Bean中的一些属性.对结果进行排序和依照条件查询. 不只能够作用于顶层对象,也能够作用于子对象.很多其它具体的介绍能够看我的博 ...
- MongoDB数据库的初识
1,MongoDB是基于分布式文件存储的数据库,有c++语言编写,旨在为WEB应用提供可扩展的高效性能数据存储解决方案. MongoDB是一个介于关系型数据库和非关系数据库之间的产品,是非关系数据库当 ...
- HDU1540 Tunnel Warfare —— 线段树 区间合并
题目链接:https://vjudge.net/problem/HDU-1540 uring the War of Resistance Against Japan, tunnel warfare w ...