/**
Edmonds-Karp算法是最簡單的網絡流算法,當然也比較慢複雜度爲O(V*E^2)
編寫簡單而且很好理解。。後面還會貼最快的dinic 算法
複雜度爲O(E*V^2) ( E爲邊數,V爲點數)
網絡流是個大學科,實在變化莫測,各種建圖技巧,可以說競賽考網絡流
90%考建圖,圖建好了,直接套模板即可
這裏只是簡單的網絡流模板而已
真正的學問是把實際問題轉換爲網絡流問題
百度百科裏這樣描述網絡流:
網絡流 network flows網絡流的理論和應用在不斷髮展,出現了具有增益的流、
多終端流、多商品流以及網絡流的分解與合成等新課題。網絡流的應用已遍及
通訊、運輸、電力、工程規劃、任務分派、設備更新以及計算機輔助設計等衆多領域。
據我所知:甚至炒股問題也可以轉換爲網絡流來搞
由於我也只是能看懂模板套模板而已,真正對流的理解甚微,所以就不多說了,
網絡流在競賽中很常見,屬於重點內容,圖中的一大分支,要引起足夠的重視
*/
//由於我是用手敲的,只做參考,還請自行嚴格測試
const int inf = 0x3f3f3f3f;
const int M = 100; // 結點數
int map[M][M], ans, n; //ans 爲最大流, n爲節點個數
int pre[M], que[M], vis[M];
bool bfs(int s, int t) { //源點爲s, 匯點爲t
int head=0, tail=1;
memset(vis, 0, sizeof(vis));
que[0] = s; //加入源點
vis[s] = true;
while (tail > head) {
int u = que[head++];
for (int i=0; i<=n; i++) {
if (!vis[i] && map[u][i]) {
pre[i] = u; //前驅節點
if (i == t) //到達匯點
return true;
que[tail++] = i;
vis[i] = true;
}
}
}
return false;
}
void end(int s, int t) {
int i, sum = inf;
for (i=t; i!=s; i=pre[i])
sum = min(sum, map[pre[i]][i]);
for (i=t; i!=s; i=pre[i]) {
map[pre[i]][i] -= sum;
map[i][pre[i]] += sum;
}
ans += sum;
}
void EK(int s, int t) { //調用EK()即可,nv 爲節點總數
while (bfs(int s, int t))
end(int s, int t);
}
/**
注意:
1、網絡流問題屬於有向圖問題,可是我見過無向圖的題目,
直接按無向圖添邊即可,如果不行就用鏈接表存邊,後面會貼,
不過如果遇到最小費的無向圖問題就必須用鏈接表了
2、如有多個源點匯點,一般用0做源點,n+1做匯點,添無限容量邊
3、map[][] 數組只能用一次, ans賦初值爲0
4、最大流等於最小割,網絡流還可以解決二分圖匹配問題
上面模板爲依然空間的模板,也是最好理解的一個模板,
依然的代碼風格和我很類似,所以好多東西都抄襲他的,嘿嘿
練習:POJ 1149 3281 1273 1459
*/
收藏於 2011-11-20
來自於百度空間
EK算法(連接矩陣)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.