posted
2023年05月2日
by comzyh
「網路流博大精深」—sideman語最早知道網路流的內容便是最大流問題,最大流問題很好理解:感謝whd的大力支援
解釋一定要通俗!
如右圖所示,有乙個管道系統,節點,有向管道,即有向圖一張. [1]是源點,有無限的水量,[4]是匯點,管道容量如圖所示.試問[4]點最大可接收的水的流量?
這便是簡單的最大流問題,顯然[4]點的最大流量為50
死理性派請注意:流量是單位時間內的,總可以了吧!
然而對於複雜圖的最大流方法是什麼呢,有ek,dinic,sap,etc.下面介紹dinic演算法(看**的直接點這)
dinic演算法的基本思路:
根據殘量網路計算層次圖。引自nocow,相當簡單是吧…在層次圖中使用dfs進行增廣直到不存在增廣路
重複以上步驟直到無法增廣
小貼士:
一般情況下在dinic演算法中,我們只記錄某一邊的剩餘流量.
comzyh的較詳細解釋(流程) :
dinic動畫演示
用bfs建立分層圖 注意:分層圖是以當前圖為基礎建立的,所以要重複建立分層圖
用dfs的方法尋找一條由源點到匯點的路徑,獲得這條路徑的流量i 根據這條路徑修改整個圖,將所經之處正向邊流量減少i,反向邊流量增加i,注意i是非負數
重複步驟2,直到dfs找不到新的路徑時,重複步驟1
注意(可以無視):
對於反向弧(反向邊)的理解:
這一段不理解也不是不可以,對於會寫演算法沒什麼幫助,如果你著急,直接無視即可.
先舉乙個例子(如右圖):
在這幅圖中我們首先要增廣1->2->4->6,這時可以獲得乙個容量為2的流,但是如果不建立4->2反向弧的話,則無法進一步增廣,最終答案為2,顯然是不對的,然而如果建立了反向弧4->2,則第二次能進行1->3->4->2->5->6的增廣,最大流為3.
comzyh對反向弧的理解可以說是」偷梁換柱「,請仔細閱讀:在上面的例子中,我們可以看出,最終結果是1->2->5->6和1->2->4->6和1->3->4->6.當增廣完1->2->4->5(代號a)後,在增廣1->3->4->2->5->6(代號b),相當於將經過節點2的a流從中截流1(總共是2)走2->5>6,而不走2->4>6了,同時b流也從節點4截流出1(總共是1)走4->6而不是4->2->5->6,相當於ab流做加法.
簡單的說反向弧為今後提供反悔的機會,讓前面不走這條路而走別的路.
alwa同學非要我給他的文章加乙個鏈結,大家可以看看他的文章: 有關網路流中的反向弧和增廣路
dinic演算法的程式實現
最大流演算法一直有乙個入門經典題:poj 1273 或者是ucaco 4_2_1 來自nocow(中文) 這兩個是同乙個題
給出這道題的**:
[cpp]view plain
copy
#include
#include
#include
#include
#define min(x,y) ((x
using
namespace
std;
const
intmax=0x5fffffff;
//int
tab[250][250];
//鄰接矩陣
intdis[250];
//距源點距離,分層圖
intq[2000],h,r;
//bfs佇列 ,首,尾
intn,m,ans;
//n:點數;m,邊數
intbfs()
} if(dis[n]>0)
return
1;
else
return
0;//匯點的dis小於零,表明bfs不到匯點
} //find代表一次增廣,函式返回本次增廣的流量,返回0表示無法增廣
intfind(
intx,
intlow)
//low是源點到現在最窄的(剩餘流量最小)的邊的剩餘流量
return
0;
} int
main()
ans=0;
while
(bfs())
//要不停地建立分層圖,如果bfs不到匯點才結束
printf("%d\n"
,ans);
} system("pause"
);
}
另一道題目是poj1742 使用鄰接表,採用當前弧優化
[cpp]view plain
copy
#include
#include
#include
#include
#include
using
namespace
std;
intn, np, nc, m;
struct
edge
edge(int
u, int
v, int
cap): u(u), v(v), cap(cap) {}
} es[150 * 150];
intr, s, t;
vector
> tab[109];
// 邊集
intdis[109];
intcurrent[109];
void
addedge(
intu,
intv,
intcap)
intbfs()
} } return
dis[t]
// 返回是否能夠到達匯點
} int
dinic(
intx,
intmaxflow)
} } return
0; // 找不到增廣路 退出
} int
dinic()
return
ans;
} int
main()
for(int
i = 0; i
for(int
i = 0; i
printf("%d\n"
, dinic());
} return
0;
}
網路最大流入門
網路最大流是網路流中最基礎也是最重要的部分,後邊的許多模型也都是由最大流問題引申而來的 在研究這個問題之前,讓我們先來學習一下前置知識 設 f u,v 表示邊 u,v 的當前容量上限 設 c u,v 表示邊 u,v 的最大容量上限 如果網路流圖中的流量滿足 則稱該流為乙個可行流 增廣 即增加一條路徑...
網路流的最大流入門(從普通演算法到dinic優化)
網路流 network flows 是一種模擬水流的解決問題方法,與線性規劃密切相關。網路流的理論和應用在不斷發展。而我們今天要講的就是網路流裡的一種常見問題 最大流問題。最大流問題 maximum flow problem 一種組合最優化問題,就是要討論如何充分利用裝置的能力,使得運輸的流量最大,...
poj 1273 EK最大流入門題
題意 給n條邊,從 fr 到 to,有乙個容量 num。然後問從1 流到 m,最多能流多少。解析 用ek求最大流,資料量比較小。include include include include include include include include include include includ...