網路流之最大流(Dinic演算法)
阿新 • • 發佈:2018-12-14
程式碼對應於 POJ - 3281
#include <iostream> #include <cstring> #include <cstdio> #include <queue> #define fuck cout << "wtf????\n" using namespace std; const int maxn = 300000; const int inf = 0x3f3f3f3f; class Dinic { private: int s, t; int cnt; int head[maxn], next[maxn]; int V[maxn], W[maxn]; int depth[maxn]; int cur[maxn]; public: int n; void init(int nn, int ss, int tt) { n = nn; s = ss; t = tt; cnt = -1; memset(head, -1, sizeof head); memset(next, -1, sizeof next); return ; } void _Add(int u, int v, int w) { cnt ++; next[cnt] = head[u]; V[cnt] = v; W[cnt] = w; head[u] = cnt; } void Add_Edge(int u, int v, int w) { _Add(u, v, w); _Add(v, u, 0); } int dfs(int u, int dist) { if(u == t) { return dist; } for(int i = head[u]; i != -1; i = next[i]) { if(depth[V[i]] == depth[u] + 1 && W[i] != 0) { int di = dfs(V[i], min(dist, W[i])); if(di > 0) { W[i] -= di; W[i ^ 1] += di; return di; } } } return 0; } bool bfs() { queue <int> Q; memset(depth, 0, sizeof depth); depth[s] = 1; Q.push(s); while(!Q.empty()) { int now = Q.front(); Q.pop(); for(int i = head[now]; i != -1; i = next[i]) { if(W[i] > 0 && depth[V[i]] == 0) { depth[V[i]] = depth[now] + 1; Q.push(V[i]); if(V[i] == t) { return true; } } } } return false; } int dinic() { int ans = 0; while(bfs()) { int d = dfs(s, inf); ans += d; } return ans; } }; int main() { //freopen("in.txt", "r", stdin); int N, F, D; cin >> N >> F >> D; Dinic C; int ss = 1, tt = 1 + F + 2 * N + D + 1; C.init(2 * N + F + D + 2, ss, tt); for(int i = 1; i <= F; ++ i) { C.Add_Edge(ss, ss + i, 1); ///食物連線源點 } for(int i = 1 + F + 2 * N + 1; i < tt; i ++) { C.Add_Edge(i, tt, 1); ///飲料連線匯點 } int fi, di, f, d; for(int i = 1; i <= N; ++ i) { C.Add_Edge(ss + F + i, ss + F + N + i, 1); cin >> fi >> di; while(fi --) { scanf("%d", &f); C.Add_Edge(ss + f, ss + F + i, 1); } while(di --) { scanf("%d", &d); C.Add_Edge(ss + F + N + i, ss + F + 2 * N + d, 1); } } cout << C.dinic() << endl; return 0; }