證明增廣路演算法的正確性及dinic演算法的使用

2021-07-15 19:24:04 字數 1403 閱讀 9226

一直對增廣路這種貪心思想表示懷疑,今天看到乙個很好的證明。

首先介紹割的概念,所謂圖的割,指的是某個頂點集合s屬於v,從s出發的所有邊的集合成為割(s,v\s),這些邊的容量和被稱為割的容量,如果有源點s屬於s,匯點t屬於v\s,則稱之為s-t割,如果將s-t割的所有邊都在原圖中去掉,則不再有s->t的路徑。

容易得到,對於任意乙個s-t割,總有f的流量<=割的容量,根據平衡條件,當且僅當割為最小割,流為最大流時去等號

首先,對於ford-fulkerson演算法求出的流為f,f對應的殘餘網路中從s可達的頂點集合為s,因為f對應的殘餘網路中不存在從s->t的路徑了,那麼顯然,在殘餘網路中,任意一條從s->

v\s 中的邊流量f=c,任意一條從反向弧f=0,這個一定是滿足,如果不滿足,那麼s集合還可以擴充頂點,與前提矛盾。因此,s->v\s的割的容量等於流的大小。則可以證明裸的増廣路ford演算法是正確的。

再說一下dinic演算法,dinic演算法總是尋找最短的増廣路並沿著它增廣,増廣路的長度不會在增廣過程中改變,則當無法增廣時,說明分層圖上沒有可以增廣的路線了,這有兩種情況,第一,已經求出了最大流,第二,可能存在長一些的増廣路可以繼續增廣,因此,繼續bfs構造分層網路。每次完成後最短増廣路長度+1,由於最短路

#include #include #include #include #include #include using namespace std;

const int max_node = 20;

const int inf = 0x3f3f3f3f;

struct edge

};vectorg[max_node];

int node_num,edge_num;

int dis[max_node]; //各頂點到源點的無權距離,通過bfs得到

int cur[max_node]; //當前弧優化

void push_edge(int from,int to,int cap)

void bfs()}}

}int dfs(int u, int v, int res)}}

return 0;

}int maxflow()

//在當前分層圖上進行最短路增廣,如果無法繼續增廣,則說明當前分層圖不存在增廣路了,需要重新構造更長路徑的分層圖

while( int x = dfs(1, node_num, inf) )

}}int main(){

#ifdef local_debug

freopen("input.txt" ,"r", stdin);

#endif // local_debug

int t,cas=1;

scanf("%d" ,&t);

while(t--){

printf("case %d: ",cas++);

for(int i=0; i

證明增廣路演算法的正確性

一直對增廣路這種貪心思想表示懷疑,今天看到乙個很好的證明 首先介紹割的概念,所謂圖的割,指的是某個頂點集合s屬於v,從s出發的所有邊的集合成為割 s,v s 這些邊的容量和被稱為割的容量,如果有源點s屬於s,匯點t屬於v s,則稱之為s t割,如果將s t割的所有邊都在原圖中去掉,則不再有s t的路...

關於最大流增廣路徑演算法的正確性的證明

最大流增廣路徑演算法也叫ford fulkerson演算法,這個演算法的思想很簡單。即找一條從s到t的增廣路徑,然後對找到的增廣點列進行流值的修改,一直迭代直到沒有增廣路徑結束。具體步驟 d v,a,s,t,c 中每一條弧的值初始化為0 1.s是源點,設點集 u s 弧的集合 b為空集 2.弧 a ...

krusal演算法正確性的證明

krusal演算法步驟如下 新建圖g,g中擁有原圖中相同的節點,但沒有邊 將原圖中所有的邊按權值從小到大排序 從權值最小的邊開始,如果這條邊連線的兩個節點於圖g中不在同乙個連通分量中,則新增這條邊到圖g中 重複3,直至圖g中所有的節點都在同乙個連通分量中 為什麼這一定是最小生成樹呢?關鍵還是步驟3中...