$Edmonds-Karp$[網絡流]

\(原題戳這裏\)


>最大流最小割定理$(Maximum Flow, Minimum Cut Theorem): $c++

網絡的最大流等於最小割

具體的證實分三部分
1.任意一個流都小於等於任意一個割 這個很好理解 自來水公司隨便給你家通點水 構成一個流 恐怖分子隨便砍幾刀 砍出一個割 因爲容量限制 每一根的被砍的水管子流出的水流量都小於管子的容量 每一根被砍的水管的水原本都要到你家的 如今流到外面 加起來獲得的流量仍是等於原來的流 管子的容量加起來就是割 因此流小於等於割 因爲上面的流和割都是任意構造的 因此任意一個流小於任意一個割
2.構造出一個流等於一個割 當達到最大流時 根據增廣路定理 殘留網絡中s到t已經沒有通路了 不然還能繼續增廣 咱們把s能到的的點集設爲S 不能到的點集爲T 構造出一個割集\(C[S,T] S\)到T的邊必然滿流 不然就能繼續增廣 這些滿流邊的流量和就是當前的流即最大流
把這些滿流邊做爲割 就構造出了一個和最大流相等的割
3.最大流等於最小割 設相等的流和割分別爲Fm和Cm 則由於任意一個流小於等於任意一個割 任意\(F≤Fm=Cm≤任意C\) 定理說明完成,證實以下: 對於一個網絡流圖\(G=(V,E)\),其中有源點s和匯點t,那麼下面三個條件是等價的:git

  1. 流f是圖G的最大流
  2. 殘留網絡Gf不存在增廣路
  3. 對於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\)spa

因爲f的上界爲最小割,當f到達割的容量時,顯然就已經到達最大值,所以f爲最大流。 這樣就說明了爲何找不到增廣路時,所求得的必定是最大流。
源點:只有流出去的點
匯點:只有流進來的點
流量:一條邊上流過的流量
容量:一條邊上可供流過的最大流量
殘量:一條邊上的容量-流量
EK時間複雜度:\(O(n m^2)\)code

#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;
}
相關文章
相關標籤/搜索