最大網路流——增廣路演算法

來源:互聯網
上載者:User

標籤:ace   標記   資訊   noi   main   UI   lib   頂點   queue   

 

幾句廢話:
讀了劉汝佳的書之後,感覺一切都是那麼茫然,於是自己在網上找教程,自己一點點碼的,大概用了三天。
網路流基礎:
看來我很有必要說一下網路流的基礎
網路流問題就是給你一個圖,每個圖的邊權叫做這條邊的流量,問你從起始點出發,有多少值能通過這些邊流到重點
我知道你沒看懂,舉個例子:

最大值為

從1到2到4運6個

從1到2到3到4運1個

從1到3到4運3個

一共運10個。

舉例說完了,那麼我說幾個定義:

容量,就只一條邊的權值,表示能從這條邊運送的最大值

流量,表示一條邊實際上流過的最大值

那麼,說演算法的時間到了,還是先上資料

(資料為所示)

4 5//四個點,五條邊1 2 81 3 32 3 12 4 63 4 5

開始,我們假設所有邊的流量都是0

以這個資料,這樣可以達到。

於是我們試圖增加一些變得流量,使得重點的流量更大。

那麼如何增加?就需要我們找増廣路。

什麼是増廣路,就是一條從起點,到終點的一條每條邊容量-實際流量>的路0。

比如

0/8表示一條邊流量為0,容量為8

現在很明顯可以看出,存在一條増廣路1——2——4

然後怎麼辦,把這條路上的每條邊流量都加上每條邊容量與流量差的最小值

例如8-0>6-0 因此1——2、2——4這兩條邊的流量都加上6,並且答案也加上6

然後我們繼續找増廣路,又發現一條1——2——3——4

還是按剛才的,找出最小值,為1,所以這條增光路上每一邊流量加1

然後ans再加一變成7

然而我們繼續找増廣路,發現1——3——4

按照剛才,流量加上2,變成

ans加上3變成10

然後發現沒有増廣路了,於是演算法結束,答案是10.

等等,這就要上代碼了?傳說中得noi演算法網路流就這麼簡單?不存在的

細心的同學(滑稽)會發現,這種情況就很神奇

你可能回算1——2——3——4這條増廣路,於是答案是1,但是事實證明最優答案明顯是2,那麼問題出在哪裡?

因為我們沒有給予返回的機會,也就是相當於第一次找到的不是最優解,那麼怎麼辦?

所以,我們要有一個反向邊,來給程式反悔的機會,每條邊都建立一條反向邊,反向邊的初始容量是0,流量都為負數。

假設1——2這條邊本來權值是1,流量也是1,那麼他的反向邊的容量是0,流量是-1,這個應該好理解。

就會變為:

 

然後以剛才舉例,當確定増廣路1——2——3——4後,圖是這樣的:

 

於是,我們又找到了一條新的増廣路:1——3——2——4

(因為0-(-1)=1,所以這條邊也可以走)

那麼答案是1+1=2

那麼問題來了,為什麼這樣就算一種呢?

因為製造相反邊,如2——3,就是相當於吧原來從而流到3的量流回來了。

這樣就可以求出最大值。

口胡內容就到這裡,其實我寫的不是很清楚,大家看劉汝佳的可能會更清楚一些,但是重點來了!!!

這道題代碼實現非常之困難,至少對於我來說,所以劉汝佳的代碼我壓根沒看懂。

因此,我自己寫得一份淺顯易懂的代碼

沒有vector!!!沒有指標!!!

而且有複雜的注釋!!!

#include <iostream>#include <cmath>#include <cstdio>#include <algorithm>#include <cstdlib>#include <cstring>#include <queue>using namespace std;int n,m;//n個點,m條邊 int head[100010];//這是鄰接表的標誌,head[i]表示以i為頂點的第一條邊 struct edge{    int cap,flow;//cap為容量,flow為流量     int from,to;//一條邊的起點終點     int next;//和這條邊起點相同的下一條邊(鄰接表標誌) }map[100010];int index=-1;//鄰接表輸入數組 int flag=0;//退出的標記 void build_edge(int a,int b,int c)//構造鄰接表,插入串連表 {    index++;    map[index].from=a;    map[index].to=b;    map[index].cap=c;    map[index].flow=0;    map[index].next=head[a];    head[a]=index;    index++;    map[index].from=b;//插入相反邊     map[index].to=a;    map[index].cap=0;    map[index].flow=0;    map[index].next=head[b];    head[b]=index;    return ;}int bfs()//運用bfs找到増廣路 {    int min_flow[100010];//min_flow[i]代表到第i好點時,當前所走過變的容量-流量的最小值     memset(min_flow,0,sizeof(min_flow));    queue<int> Q;//用隊列 維護     min_flow[1]=999999;//開始為無限大     int p[100010];//這個很重要,構造增光路時,記錄當前點是由那條邊找到的,以此找到増廣路時能從終點以此到起點的邊的流量加上最小值     p[1]=-1;    Q.push(1);//起點入隊     while(!Q.empty())    {        int now=Q.front();        Q.pop();        for(int e=head[now];e!=-1;e=map[e].next)//鄰接表枚舉當前點的所有連邊         {            int v=map[e].cap-map[e].flow;//v就是為當前邊容量-流量             if(v>0 && !min_flow[map[e].to])//當v>0 並且這個點沒有訪問過時             {                p[map[e].to]=e;//記錄到達這個點的邊的序號                 min_flow[map[e].to]=min(min_flow[now],v);//維護最小值                 Q.push(map[e].to);//維護bfs             }        }        if(min_flow[n]!=0)//如果終點得到更新,說明找到増廣路,直接break             break;    }    if(min_flow[n]==0)//當沒有更新到終點,也就是重點最小增加值為0時,說明沒有増廣路了,直接完事         flag=1;    for(int e=n;;e=map[p[e]].from)//從終點開始,以此倒著走増廣路,把沿途上邊的流量都加上終點最小更新值     {        if(p[e]==-1)//如果到頭就完事             break;         map[p[e]].flow+=min_flow[n];//流量加上最小更新至          map[p[e]^1].flow-=min_flow[n];//反向邊減去     }    return min_flow[n];//返回最小更新至,加到答案當中 }int max_flow(){    int flow=0;//這就是神聖的答案     while(1)    {        flow+=bfs();//迴圈搜尋         if(flag==1)//沒有増廣路,就直接跳出             break;    }    return flow;//返回答案 }int main(){    cin>>n>>m;    for(int i=0;i<=m;i++)//初始化,很重要,制勝之點     {        map[i].next=-1;         head[i]=-1;    }    for(int i=1;i<=m;i++)//讀入,構造鄰接表     {        int a,b,c,d;        cin>>a>>b>>c;        build_edge(a,b,c);    }    cout<<max_flow();//輸出答案 }/*測試資料 4 41 2 22 4 21 3 33 4 1*/

學資訊不易,作業還沒動,求關注!!!

 

最大網路流——增廣路演算法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.