上下界網路流初探

2021-06-27 23:39:11 字數 3496 閱讀 7601

看文章各種不明真相...

請教了一下iwtwiioi大牛...大致有個理解....

建模過程

1.拆邊. 對於每一條給出的有向邊(u,v,c,d) ,其中c指下界,d指上界,那麼在實際的圖中連三條只有上界沒有下界的邊:

(s,v,c) (u,t,c) (u,v,d-c) 其中s是超級源,t是超級匯.(不同於題目給出的源與匯)

一條是超級源連向邊的終點.

第二條是邊的起點連向超級匯.

第三條是原來的邊更改了權值.

最後,從匯向源連一條沒有上下界的邊(如果題目給定了源與匯).

然後跑s到t的最大流,得出來的就是可行流.

再從源到匯跑一遍最大流,所得流量就是最大流.

ps:神犇們說可行流流量+第二遍最大流的流量才是真正的流量...

但是為什麼我的程式正確答案直接就是第二遍最大流的流量呢..

發現原來是匯到源的那條邊在搞鬼.....

第一遍可行流的流量一定等於匯到源那條邊的流量(因為原圖沒有環,是環流就必定經過這條邊)

那麼第二遍跑最大流的時候,源會直接通過那條邊給出與可行流相等的流量.

當然除去此邊,那些權值為d-c的邊的流量還是需要把可行流流量加上去才行.

常數優化

只要是個流量網路,那麼重邊必定可以合併成一條邊(不是最小費)

按照上邊的方法,每條原式邊對應的實際邊數是3.我們處理那些像(sut)的路徑(從超級源直接連向點u,又從u連向點超級匯),讓它們最多連線s,t中的乙個.

直接統計入度和出度最後再構造邊即可.

原理(?)

嚴謹證明的不會(要滾去好好看圖論啊喂)

根據iwtwiioi介紹的思路......

-我們想要把一條邊的最小容量塞滿....那麼邊的起點要能給出這麼多流量,邊的終點要能接受這麼多流量.

-那麼我們就直接從超級源給出流量看終點能不能接受.

-以及從起點接收流量看我們能不能得到這麼多.

我的理解...

首先有源匯的上下界網路流能轉變為無源匯的上下界網路流.

所以考慮無源匯的網路流.

注意到每個點的入流等於出流.

說明什麼呢?

每一道流(流量為1)總是會構成乙個圈,乙個環流. 可行流就是由一些環流構成的.

怎麼證明呢? 假設有一道流不是環流,那麼它就有兩個端點,假設它從點a流向點b.

想要這兩個端點的入流量等於出流量,只能再多一道從b到a的流補成環流.

現在可行流就是一堆的環流了.

觀察上邊所說的拆邊法,發現其實就是把環流轉成了從s到t的許多許多流而已.......

比如有環(a,b,c,d,a),最後會拆成

(s,a,t) (s,b,t) (s,c,t) (s,d,t),還有(a,b) (b,c) (c,d) (d,a)

那些並不連到s與t的邊,表示從別的邊補給流量.

比如(s,a,b,t)這道流,就是我在塞滿了b的下界以後,還從點a搬運了一些流來對b進行補給,確保b的後繼能夠得到足夠的流量.

值得注意的是,蒜搗(clrs)在思考題26-6以"負權流"的形式給出了構圖法.

如果一條(u,v)邊帶負權c(u,v),意思就是"這條邊的最大流為-c(u,v)",根據對稱性,意思就是"這條邊對應的反向邊的最小流為-c(u,v)"

這裡是模板.

有源有匯上下界最大流.

zoj3229

沒有加人和優化.

**又臭又長囧

需要再花點時間研究怎麼寫比較舒服.....(嗯然後再考慮常數優化問題....)

#include #include #include #include #include #include #include #include #include typedef unsigned int uint;

typedef long long ll;

typedef unsigned long long ull;

typedef double db;

#define dbg printf("*")

using namespace std;

struct edge

pool[1000050];

edge*et;

edge*eds[2050];

inline edge*addedge(int i,int j,int c)

#define foreach_edge(i,j) for(edge*i=eds[j];i;i=i->nxt)

const int inf=(1<<30)-1;

int n;

int st,ed;

int dep[2050];

bool used[2050];

int dfs(int x,int mi)

used[x]=false;

if(res<=0) dep[x]=-1;

return res;

}int q[2050];

int qh,qt;

int dinic(int s,int e)

qh++;

} if(dep[ed]==-1) break;

res+=dfs(st,inf); }

return res;

}int dtot,gtot;

//blocks define

#define time(i) (i)

#define girl(i) (dtot+i)

#define source (dtot+gtot)

#define sink (dtot+gtot+1)

#define ssource (dtot+gtot+2)

#define ssink (dtot+gtot+3)

edge*rd[400000];

edge*rt[400000];

int rtot;

inline void addedge_lim(int i,int j,int c,int d,int k) //c is the lower limit.

int r[400000];

int main()

if(!ok)

//record

for(int i=0;ic;

//original max flow

foreach_edge(i,ssource)

foreach_edge(i,ssink)

int maxflow=dinic(source,sink);

printf("%d\n",maxflow);

for(int i=0;ic);

printf("\n"); }

return 0;

}

上下界網路流專題

給定n點m邊無向圖,用k個人從起點出發,乙個人走一條路代價為路的長度li,你希望按照0,1,2,n的順序依次經過這些點,其中經過的定義是任何1人經過該點,問k個人最小的道路總和。n 150,m 20 000,1 k 10,li 10 000 考慮每次只有1個人走1步,已經過t點,則每次其中一人走向t...

有上下界網路流

前言 下面寫得只是一些十分基礎的東西,是給我以後自己看的,想要徹底弄明白這個內容,推薦去看liu runda。注 為了方便,下面所有的 x,y,l,r 都表示一條從x連向y,流量下界為l,流量上界為r的邊。問題簡述 給出乙個有向圖,每條邊有流量上下界,沒有源點和匯點,要求找到一種流的方法,使得每個點...

上下界網路流總結

orz zhhx orz yyb orz aysn 無源匯可行流 每條邊取 l i 最大流調整 有源匯可行流 e t,s,inf 無源匯可行流 有源匯最小流 有源匯可行流 去掉 inf 邊 t rightarrow s 最大流 有源匯最大流 有源匯可行流 去掉 inf 邊 s rightarrow ...