日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

网络流-EK求最大流

發布時間:2023/12/19 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络流-EK求最大流 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

網絡流-EK求最大流

2021.8.17

網絡流最大流解決什么問題?

網絡流(network-flows)是一種類比水流的解決問題方法(摘自百度百科),最大流是求源點到匯點最大流量的方法。

算法原理

已知起點到終點,很容易想到深搜\廣搜求最大值的方式,但是,在最大流問題中,會出現如下情況:

假設1為源點,4為匯點,若對其進行搜索,路徑可能有1->2->3->4,隨后標記數組有如下標記:

那么,此時,流經1-2線路的水流,匯入了3號節點最終流向4號節點,此時3-4路徑已經被灌滿,2-4路徑沒有水流流入,最終匯入匯點的水流量為1。

但是,對于上述情況,最大流應該是如下情形:

此時匯點流入流量為2.

那么,在建圖順序位置時,如何計算出最大的流量?

退回流量,構建增廣路徑,當流量匯入其他渠道并且有部分無法匯入匯點,那么就代表其應該回到原渠道,按照原渠道走,但是搜索起來肯定難以實現,因此需要建立一條相反的路徑,讓流過去的水流能有機會返回原來的渠道,并且最多返回流過去的水流。(不管水流走在哪里,只要流入匯點即可,不必求出其準確的路徑)如下圖:

如此,在1-3路徑中的水流流入3號節點時,可以通過2-3路徑流回2號節點,再從2-4路徑流入4號匯點,此時便可得最大流量為2.(若1-3為2,則也只能退回1).

但是通常情況下,退流一次并不會得到最大流,因此需要多次搜索多次退流。在EK求最大流中,每次選擇在部分流量匯入匯點后,對路徑的可行流進行更改,構建增廣路徑。此時圖中每個點的殘留量不影響結果,因再次搜索時只計算從源點流出的流量。

對其搜索時,正常進行搜索即可:

bool bfs() {queue<int>q;memset(vis, 0, sizeof vis);q.emplace(S); vis[S] = true, d[S] = 0x3f3f3f3f;while (!q.empty()) {int t = q.front(); q.pop();for (int i = head[t]; !i; i = nexte[i]) {int k = to[i];if (!vis[k] && wei[i]) {vis[k] = 1;d[k] = min(d[t], wei[i]);pre[k] = i;if (k == T)return true;q.emplace(k);}}}return false; }

其中,d數組記錄路徑最多流過的流量,pre數組記錄路徑編號,當成功匯入匯點,則跳出。

每次對路徑進行更新時,則對上一步搜索到的路徑進行退流:

int EK() {int res = 0;while (bfs()) {//搜索直到沒有可行流res += d[T];for (int i = T; i != S; i = to[pre[i] ^ 1])//建圖時,反向邊編號比正向邊多1wei[pre[i]] -= d[T], wei[pre[i] ^ 1] += d[T];//構建增廣路徑}return res; }

最終返回的res即為最大流。
注:正向路徑同樣要減去相應的流量大小,因路徑已經被部分或全部占用。

模板代碼

代碼

#include<iostream> #include<algorithm> #include<stdio.h> #include<string> #include<string.h> #include<queue>using namespace std;int nexte[20005], wei[20005], to[20005], head[20005]; int n, m, S, T; int idx; int pre[20005], d[20005]; bool vis[20005];void addedge(int u, int v, int c) {to[idx] = v, wei[idx] = c, nexte[idx] = head[u], head[u] = idx++;to[idx] = u, wei[idx] = 0, nexte[idx] = head[v], head[v] = idx++; }bool bfs() {queue<int>q;memset(vis, 0, sizeof vis);q.emplace(S); vis[S] = true, d[S] = 0x3f3f3f3f;while (!q.empty()) {int t = q.front(); q.pop();for (int i = head[t]; !i; i = nexte[i]) {int k = to[i];if (!vis[k] && wei[i]) {d[k] = min(d[t], wei[i]), pre[k] = i;if (k == T)return true;q.emplace(k);vis[k] = 1;}}}return false; }int EK() {int res = 0;while (bfs()) {res += d[T];for (int i = T; i != S; i = to[pre[i] ^ 1])wei[pre[i]] -= d[T], wei[pre[i] ^ 1] += d[T];}return res; }int main() {cin >> n >> m >> S >> T;memset(head, -1, sizeof head);for (int i = 0; i < m; i++){int a, b, c;cin >> a >> b >> c;addedge(a, b, c);}cout << EK() << endl;return 0; }

總結

以上是生活随笔為你收集整理的网络流-EK求最大流的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。