給出乙個網路圖,以及其源點和匯點,求出其網路最大流。
可以把網路圖看作管道,節點看作管道的交界處。流就像是管道裡的流水。管道有個容量(相當於橫截面積),還會有個流量(相當於水流佔了管道的多少橫截面積)。管道的交界處的流量滿足流入的流量和等於流出的流量和。網路圖有源點和匯點,水流必須從源流到匯。現在要你求整個圖中的最大流(也就是從源點流出的流量的最大值)。
在當前水流流動的情況下,對於乙個從源點到匯點的路徑,如果組成該路徑的邊都沒有滿流,則該路徑便是乙個增廣路徑。
顯然,當前圖的水流流動的情況下不存在增廣路徑當且僅當當前圖中的總流量為圖的最大流。
不斷地將流量盡量大的水流注入管道,直到網路圖中沒有增廣路徑為止。
圖中每條邊儲存的是當前邊的剩餘容量。對以下操作迴圈:首先從源點bfs,對當前的可增廣路徑進行搜尋,設定每乙個節點的level。節點的level表示水流在網路圖中流經的節點的順序。隨後dfs,根據bfs所得的level的順序向當前可增廣路徑中注入流量盡可能大的水流。
此處有個問題,處理當前可增廣路徑後的水流狀態不一定就是最大流的水流狀態呀!所以我們還要對每一條邊設定一條反向邊,以達到給機會後悔的目的,其初值為0。dfs求出當前節點的下乙個節點用去的水流nexttake後,當前邊剩餘容量-=nexttake,其反向邊的容量+=nexttake。
最後,當bfs後,如果匯點的level沒有設定上,意味著不存在增廣路徑了,此時輸出結果:每次迴圈所得的匯點流出的流量之和。
對於每乙個節點我們可以設定乙個dfsfrom,每次dfs時,從dfsfrom開始遍歷。具體步驟看**。注意dfs中for括號裡和迴圈後對dfsfrom的處理。
#include #include #include #include using namespace std;const int max_node = 10010, max_edge = 100010 * 2, inf=0x3f3f3f3f;
#define loop(i, n) for(int i=1; i<=n; i++)
struct dinic
_nodes[max_node], *start, *target;
int _vcount;
struct edge
*_edges[max_edge];
int _ecount;
edge *newedge()
edge *addedge(node *from, node *to, int cap)
bool bfs()
}} return target->level;
} int dfs(node *cur, int limit)
if (limit - curtake == 0)//易忘點
break;
} return curtake;
}public:
void build(int uid, int vid, int cap)
int proceed()
return ans;
} dinic() {}
dinic(int totnode, int sid, int tid):_vcount(totnode),start(_nodes+sid),target(_nodes+tid) };
int main()
int ans;
ans = g.proceed();
printf("%d\n", ans);
}
luogu3376 模板 網路最大流
題目描述 如題,給出乙個網路圖,以及其源點和匯點,求出其網路最大流。輸入輸出格式 輸入格式 第一行包含四個正整數n m s t,分別表示點的個數 有向邊的個數 源點序號 匯點序號。接下來m行每行包含三個正整數ui vi wi,表示第i條有向邊從ui出發,到達vi,邊權為wi 即該邊最大流量為wi 輸...
P3376 模板 網路最大流
網路流用於解決流量問題 網路流 所有弧上流量的集合f 稱為該容量網路的乙個網路流。1 定義 帶權的有向圖g v,e 滿足以下條件,則稱為網路流圖 flow network 僅有乙個入度為0的頂點s,稱s為源點。僅有乙個出度為0的頂點t,稱t為匯點。每條邊的權值都為非負數,稱為該邊的容量,記作c i,...
Luogu P3376 模板 網路最大流
傳送門 noip之前,我絕對不學網路流。我網路流可以解決這樣一類問題 給定乙個有向圖,每條邊有乙個流量上限,求從源點到匯點所能運輸的最大流量。解決這類問題的一種演算法叫做 dinic 一些性質 對於任意乙個時刻,設c u,v 為容量,f u,v 為實際流量,則整個圖g的流網路滿足3個性質 原理 假設...