网络流最大流——Dinic算法
Posted ignorance
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络流最大流——Dinic算法相关的知识,希望对你有一定的参考价值。
Dinic 时间复杂度最坏 O(n*n*m) 平均O(n)。
算法思路:用BFS构建层次图,如果汇点不在层次图中则结束算法返回最大流,否则在层次图中DFS找到图中所有增广路,增广结束后重新建立层次图。
优化:多路增广优化:将节点的所有增广路的到的流量记录下来直接返回。
炸点优化:若改点无流量直接弃掉。
code:
#include <iostream> #include <string> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <functional> #include <map> #include <set> #include <stack> #define FT(a, b) memset(a, b, sizeof(a)) #define FAT(a) memset(a, 0, sizeof(a)) using namespace std; typedef long long ll; const int M = 2e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int n, m, s, t; int h[M], e[M], ne[M], w[M], idx; int deepth[M]; void add(int a, int b, int c) { e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; } bool bfs()// bfs求深度 { FT(deepth, -1); queue<int> q; q.push(s); deepth[s] = 0; while (!q.empty()) { int a = q.front(); q.pop(); for (int i = h[a]; ~i; i = ne[i]) { int j = e[i]; if (w[i] && deepth[j] == -1)//只有未被访问过且还有流量 { deepth[j] = deepth[a] + 1; q.push(j); } } } return deepth[t] != -1; } int dfs(int now, int flow) { if (now == t) return flow; int nowflow = 0; //多路增广优化 for (int i = h[now]; ~i; i = ne[i]) { int j = e[i]; if (w[i] && deepth[j] == deepth[now] + 1)// 必须有流量且比上一个点深 { int k = dfs(j, min(flow, w[i])); w[i] -= k; w[i ^ 1] += k; flow -= k; nowflow += k; } } if (!nowflow) deepth[now] = -2; //炸点优化 return nowflow; } int dinic() { int ans = 0; while (bfs()) ans += dfs(s, INF); return ans; } int main() { #ifdef ONLINE_JUDGE #else freopen("D://code//c++//in.txt", "r", stdin); #endif scanf("%d%d%d%d", &n, &m, &s, &t); FT(h, -1); idx = 0; for (int i = 0; i < m; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a, b, c), add(b, a, 0); } printf("%d ", dinic()); return 0; }
以上是关于网络流最大流——Dinic算法的主要内容,如果未能解决你的问题,请参考以下文章