一直對增廣路這種貪心思想表示懷疑,今天看到乙個很好的證明。
首先介紹割的概念,所謂圖的割,指的是某個頂點集合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中...