1. 程式人生 > >網路流之最大流演算法(EdmondsKarp)

網路流之最大流演算法(EdmondsKarp)

求網路流有很多演算法,這幾天學習了兩種,記錄一下EK演算法。

首先是網路流中的一些定義:

V表示整個圖中的所有結點的集合.
E表示整個圖中所有邊的集合.
G = (V,E) ,表示整個圖.
s表示網路的源點,t表示網路的匯點.
對於每條邊(u,v),有一個容量c(u,v)   (c(u,v)>=0),如果c(u,v)=0,則表示(u,v)不存在在網路中。相反,如果原網路中不存在邊(u,v),則令c(u,v)=0.
對於每條邊(u,v),有一個流量f(u,v).

一個簡單的例子.網路可以被想象成一些輸水的管道.括號內右邊的數字表示管道的容量c,左邊的數字表示這條管道的當前流量f.


網路流的三個性質:

1、容量限制:  f[u,v]<=c[u,v]
2、反對稱性:f[u,v] = - f[v,u]
3、流量平衡:  對於不是源點也不是匯點的任意結點,流入該結點的流量和等於流出該結點的流量和。

只要滿足這三個性質,就是一個合法的網路流.

最大流問題,就是求在滿足網路流性質的情況下,源點 s 到匯點 t 的最大流量。

求一個網路流的最大流有很多演算法 這裡首先介紹 增廣路演算法(EK)

學習演算法之前首先看了解這個演算法中涉及到的幾個圖中的定義:

**殘量網路

為了更方便演算法的實現,一般根據原網路定義一個殘量網路。其中r(u,v)為殘量網路的容量。
r(u,v) = c(u,v) – f(u,v)
通俗地講:就是對於某一條邊(也稱弧),還能再有多少流量經過。
Gf
 殘量網路,Ef 表示殘量網路的邊集.


這是上面圖的一個殘量網路。殘量網路(如果網路中一條邊的容量為0,則認為這條邊不在殘量網路中。

r(s,v1)=0,所以就不畫出來了。另外舉個例子:r(v1,s) = c(v1,s) – f(v1,s) = 0 – (-f(s,v1)) = f(s,v1) = 4.

其中像(v1,s)這樣的邊稱為後向弧,它表示從v1到s還可以增加4單位的流量。

但是從v1到s不是和原網路中的弧的方向相反嗎?顯然“從v1到s還可以增加4單位流量”這條資訊毫無意義。那麼,有必要建立這些後向弧嗎?

顯然,第1個圖中的畫出來的不是一個最大流。

但是,如果我們把s -> v2 -> v1 -> t這條路徑經過的弧的流量都增加2,就得到了該網路的最大流。

注意到這條路徑經過了一條後向弧:(v2,v1)。

如果不設立後向弧,演算法就不能發現這條路徑。

**從本質上說,後向弧為演算法糾正自己所犯的錯誤提供了可能性,它允許演算法取消先前的錯誤的行為(讓2單位的流從v1流到v2)

注意,後向弧只是概念上的,在程式中後向弧與前向弧並無區別.

**增廣路

增廣路定義:在殘量網路中的一條從s通往t的路徑,其中任意一條弧(u,v),都有r[u,v]>0。


如圖綠色的即為一條增廣路。

看了這麼多概念相信大家對增廣路演算法已經有大概的思路了吧。

**增廣路演算法

增廣路演算法:每次用BFS找一條最短的增廣路徑,然後沿著這條路徑修改流量值(實際修改的是殘量網路的邊權)。當沒有增廣路時,演算法停止,此時的流就是最大流。

**增廣路演算法的效率

設n = |V|,  m = |E|

每次增廣都是一次BFS,效率為O(m),而在最壞的情況下需要(n-2增廣。(即除源點和匯點外其他點都沒有連通,所有點都只和s與t連通)

所以,總共的時間複雜度為O(m*n),所以在稀疏圖中效率還是比較高的。

hdoj 1532是一道可以作為模板題目練手。

模板程式碼:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
const int N = 1100;
const int INF = 0x3f3f3f3f;

struct Node
{
    int to;//終點
    int cap; //容量
    int rev;  //反向邊
};

vector<Node> v[N];
bool used[N];

void add_Node(int from,int to,int cap)  //重邊情況不影響
{
    v[from].push_back((Node){to,cap,v[to].size()});
    v[to].push_back((Node){from,0,v[from].size()-1});
}

int dfs(int s,int t,int f)
{
    if(s==t)
        return f;
    used[s]=true;
    for(int i=0;i<v[s].size();i++)
    {
        Node &tmp = v[s][i];  //注意
        if(used[tmp.to]==false && tmp.cap>0)
        {
            int d=dfs(tmp.to,t,min(f,tmp.cap));
            if(d>0)
            {
                tmp.cap-=d;
                v[tmp.to][tmp.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}

int max_flow(int s,int t)
{
    int flow=0;
    for(;;){
        memset(used,false,sizeof(used));
        int f=dfs(s,t,INF);
        if(f==0)
            return flow;
        flow+=f;
    }
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        memset(v,0,sizeof(v));
        for(int i=0;i<n;i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add_Node(x,y,z);
        }
        printf("%d\n",max_flow(1,m));
    }
}


相關推薦

網路Dinic演算法

程式碼對應於 POJ - 3281 #include <iostream> #include <cstring> #include <cstdio> #include <queue> #define fuck

網路演算法EdmondsKarp

求網路流有很多演算法,這幾天學習了兩種,記錄一下EK演算法。 首先是網路流中的一些定義: V表示整個圖中的所有結點的集合.E表示整個圖中所有邊的集合.G = (V,E) ,表示整個圖.s表示網路的源點

網路

在一個網路裡   對於S流到T的流量,有很多值。其中這些值的最大值,我們稱為S到T的最大流 (想象成自來水管,S就是水廠,T就是你家,邊就是管子,最大流就是能流到你家水量的最大值)   介紹三個相關的知識點  (1) 容量網路    &nbs

POJ-1273-Drainage Ditches網絡

rom lang spa bsp pen from per int eof Every time it rains on Farmer John‘s fields, a pond forms over Bessie‘s favorite clover patch. This

洛谷P4016 負載平衡問題 網路小費用

P4016 思路: 因為是每個倉庫貨物相等,那麼最後肯定是總和/個數(平均值ave)。 建圖: 源點s,匯點t。 如果i倉庫貨物大於平均值,那麼表示需要流出,所以: i -> t 流量為a[i]

hihocoder1378 網路小割

題目連結:http://hihocoder.com/problemset/problem/1378 思路: 描述 小Hi:在上一週的Hiho一下中我們初步講解了網路流的概念以及常規解法,小Ho你還記得內容麼? 小Ho:我記得!網路流就是給定了一張圖G=(V

hihocoder 1369 網路

題目連結:http://hihocoder.com/problemset/problem/1369 思路:每次找一條不停地能到達目的點的路(增廣路),然後更新圖的流量。 ,使用:Ford-Fulkerson演算法 #include <iostream> #in

網路】POJ1273-Drainage Ditche【模板題】

這是一道網路流的入門題,用來理解最大流很好。 #include<iostream> #include<string> #include<cstdio> #include<cstring> #include<map&g

hdu3549網絡

tro for eof pen tar nbsp karp none out Ford-Fulkerson方法:dfs實現 dfs 140ms #include<map> #include<set> #include<cmath>

poj3436網絡拆點

hide ring 拆點 前驅 clas view int for fff 這題看了半天看不懂題意。。。還是看的網上題意寫的 加一個源點一個匯點,把每個點拆成兩個,這兩個點的流量是v,其他聯通的邊都設為無窮大 輸入沒有1的點就與源點連接,輸出只有1的點就與匯點連接 還有這個

網絡算法

要求 -c style 相加 宋體 所有 概念 -s 流量 最大流 網絡流的定義: 在一個網絡(有流量)中有兩個特殊的點,一個是網絡的源點(s),流量只出不進,一個是網絡的匯點(t),流量只進不出。 最大

網絡

可能 pac 深度優先 bool 技術分享 模擬 機會 r+ ont 網絡流 題記:網絡流是最近講過的最迷算法…… 網絡流(network-flows)是一種類比水流的解決問題方法,與線性規劃密切相關。非常重視選手在網絡流上的建模技巧,畫圖是非常關鍵的。 1、最大流

網絡-Ford-Fullkerson算法 DFS && BFS

global log cap {} lse scan bae Go tor 理解處 刷題處 DFS #include <iostream> #include <stdio.h> #include <vector> #include &

網絡Dinic --- poj 1459

技術分享 empty ace from contain namespace edge win lin 題目鏈接 Description A power network consists of nodes (power stations, consumers and

機器學習經典演算法 PageRank演算法

PageRank演算法        (一)  PageRank演算法簡介:        Google的創始人之一LarryPage於1998年提出了PageRank,並應用在Google搜尋引擎的檢索結果排序上,該技術也是Google早期的核心技術之一。        L

演算法codeforces839E

題意理解玩,YY一下,就知道要把K平均分給最大團裡面的每個點,然後乘積和就是答案。 最大團就是有n個點的完全圖,完全圖就是n個點有n*(n-1)/2條邊的圖、有高效演算法求的。。//最大獨立集:一個

網路流入門問題1

changxv大佬說網路流非常萬能,幾乎可以解決所有與圖有關的題目(網路流的強悍!),這裡寫出部落格只是談談我自己的心得體會,幫助那些看到網路流望而卻步的同學們以及我自己有個大致瞭解。 概念: 在一張帶權圖G中,我們已知源點s與匯點t,假設我們要將水從s輸送到t,其間必然

HDU 3549網路流入門

Flow Problem Time Limit: 5000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 10327    Accepted S

網路費用

傳送門​​​​​​ 題意 現在有  n  顆糖果,要將其分給 m 個小朋友,每個小朋友都有特定的喜好,如果他得到了自己喜歡的糖果,那麼他將增加K的歡樂值,否則就只會增加1的歡樂值。當第 i 個小朋友的歡樂值大於等於Bi時,他才是高興的 問是否存在一種分配方案,使得所

網路問題Edmonds-Karp演算法

       實現最大流有好幾種演算法,比如Dinic或者ISAP演算法,Edmonds-Karp只是其中最好理解的一種演算法,它的實現要運用到增廣路與BFS,當然也可以用DFS,但效率太低。網路流這東西是用來求從s點到t點(起點為s,終點為t)的流量問題,因為類似網路資料傳