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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

网络流 (EK Dinic)

發布時間:2024/4/18 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络流 (EK Dinic) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • Edmonds-Karp
    BFS找增廣路,找到增廣路,更新殘余網絡。
// 臨接矩陣 // pre記錄前驅節點 int G[maxn][maxn], pre[maxn], vis[maxn], n, m; // BFS找增廣路 bool bfs(int s, int e) {memset(vis, 0, sizeof(vis));memset(pre, -1, sizeof(pre));pre[s] = s;vis[s] = 1;queue<int> que;que.push(s);while (!que.empty()) {int u = que.front();que.pop();// 訪問u所有的出邊, 判斷能否增廣for (int i = 0; i <= e; i++) {if (G[u][i] && !vis[i]) {pre[i] = u;que.push(i);vis[i] = 1;if (i == e) return 1; // 到匯點存在增廣路}}}return 0; } int EK(int s, int e) {int ans = 0;while (bfs(s, e)) { // 判斷是否存在增廣路int MIN = inf;// 遍歷增廣路上所有邊取流量最小的邊for (int i = e; i != s; i = pre[i]) {MIN = min(MIN, G[pre[i]][i]);}// 更新增廣路上的流量, 正向減,反向加for (int i = e; i != s; i = pre[i]) {G[pre[i]][i] -= MIN;G[i][pre[i]] += MIN;}ans += MIN;}return ans; } int cnt; struct ac{int v, c, nex; }edge[maxn << 8]; int vis[maxn], head[maxn], path[maxn]; void init() {cnt = 0;memset(head, -1, sizeof(head)); } void addedge(int u, int v, int c) {// 正向邊edge[cnt] = {v, c, head[u]};head[u] = cnt++;// 反向邊edge[cnt] = {u, 0, head[v]};head[v] = cnt++; } bool bfs(int s, int t) {memset(vis, 0, sizeof(vis));memset(path, -1, sizeof(path));queue<int> que;que.push(s);vis[s] = 1;while (!que.empty()) {int u = que.front();que.pop();// 遍歷u的所有出邊for (int i = head[u]; i != -1; i = edge[i].nex) {int v = edge[i].v;int c = edge[i].c;// 判斷能否增廣if (c == 0 || vis[v]) continue;path[v] = i;vis[v] = 1;que.push(v);if (v == t) return true;}}return false; } int EK(int s, int t) {int ans = 0;while (bfs(s, t)) {int flow = inf;for (int i = path[t]; i != -1; i = path[edge[i^1].v]) {flow = min(flow, edge[i].c);}for (int i = path[t]; i != -1; i = path[edge[i^1].v]) {edge[i].c -= flow;edge[i^1].c += flow;} ans += flow;}return ans; }
  • Dinic
struct ac{int v, c, nex; }edge[maxn << ]; int s, e; int head[maxn], dis[maxn], curedge[maxn], cnt; void init() {cnt = 0;memset(head, -1, sizeof(head)); } void addedge(int u, int v, int c) {// 正向建邊edge[cnt] = {v, c, head[u]};head[u] = cnt++;// 反向建邊, 流量為0edge[cnt] = {u, 0, head[v]};head[v] = cnt++; } bool bfs() {queue<int> que;que.push(s);memset(dis, 0, sizeof(dis)); // 對圖進行分層dis[s] = 1;while (!que.empty()) {int u = que.front();que.pop();for (int i = head[u]; i != -1; i = edge[i].nex) {int v = edge[i].v;int c = edge[i].c;// 如果節點v已經分過層或者u->v流量為0, continueif (dis[v] || c == 0) continue;dis[v] = dis[u] + 1; // 對v進行標記并加入隊列que.push(v);}}return dis[e] > 0; // 判斷是否存在增廣路,s是否能到達e }int dfs(int u, int flow) { // 增廣路走到u點的最小流量為flowif (u == e || flow == 0) return flow;// 遍歷u的所有出邊for (int &i = curedge[u]; i != -1; i = edge[i].nex) { // 當前弧優化int v = edge[i].v;int c = edge[i].c;// 判斷能否u->v增廣if (dis[v] != dis[u] + 1 || c == 0) continue;int d = dfs(v, min(flow, c));if (d > 0) { // 找到一條增廣路,修改增廣路上的正反向邊edge[i].c -= d;edge[i^1].c += d;return d;} }dis[u] = -1; // // 炸點優化return 0; } int Dinic() {int sum = 0, d;while (bfs()) { // 判讀是否存在增廣路for (int i = 0; i <= e; ++i) curedge[i] = head[i]; // copy head數組,在dfs中可以直接得到下一條沒有被增廣過的邊while ((d = dfs(s, inf)) > 0) sum += d; // 多次dfs找增廣路}return sum; }

總結

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

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