ZOJ - 2532 Internship (網路流求割邊)
阿新 • • 發佈:2018-11-10
有n個城市和m箇中轉點,0號點是匯點。問提高哪一條邊的容量可以使進入匯點的容量增加。
如果一條邊對總的流量有影響,那麼它在求完最大流的殘餘網路中肯定滿足兩個條件:第一,這條邊是滿流;第二,源點和匯點分別經過未滿流的邊可達此邊的兩個端點。
因此就是求最大流後在殘餘網路中dfs處理一下連通性,然後遍歷每一條邊判斷即可。
#include <cstdio> #include <cstring> #include <queue> #include <vector> #include <map> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 205; const int maxm = 100050; const int INF = 0x3f3f3f3f; int n, m, k, a, b, x, no, head[maxn], q[maxm]; int sta[maxn], gap[maxn], cur[maxn], level[maxn]; bool vis[maxn][2]; vector<int>ans; struct node { int from, to, nxt, id; int cap, flow; }e[maxm]; void add(int u, int v, int w, int id) { e[no].from = u, e[no].to = v, e[no].nxt = head[u]; e[no].cap = w, e[no].flow = 0, e[no].id = id; head[u] = no++; e[no].from = v, e[no].to = u, e[no].nxt = head[v]; e[no].cap = 0, e[no].flow = 0, e[no].id = id; head[v] = no++; } void bfs(int s, int t) { int fro = 0, rea = 0; memset(level, -1, sizeof(level)); memset(gap, 0, sizeof(gap)); gap[0] = 1; level[t] = 0; q[rea++] = t; while(fro != rea) { int u = q[fro++]; for(int i = head[u];i != -1;i = e[i].nxt) { int v = e[i].to; if(level[v] == -1) { level[v] = level[u] + 1; gap[level[v]]++; q[rea++] = v; } } } } int sap(int s, int t, int N) { bfs(s, t); memcpy(cur, head, sizeof(head)); int top = 0, u = s, ans = 0; while(level[s] < N) { if(u == t) { int minn = INF; int id; for(int i = 0;i < top;i++) { if(minn > e[sta[i]].cap - e[sta[i]].flow) { minn = e[sta[i]].cap - e[sta[i]].flow; id = i; } } for(int i = 0;i < top;i++) { e[sta[i]].flow += minn; e[sta[i]^1].flow -= minn; } ans += minn, top = id; u = e[sta[top]^1].to; continue; } bool flag = 0; int v; for(int i = cur[u];i != -1;i = e[i].nxt) { v = e[i].to; if(e[i].cap - e[i].flow && level[v] + 1 == level[u]) { flag = 1; cur[u] = i; break; } } if(flag) { sta[top++] = cur[u]; u = v; continue; } int minn = N; for(int i = head[u];i != -1;i = e[i].nxt) { if(e[i].cap - e[i].flow && minn > level[e[i].to]) { minn = level[e[i].to]; cur[u] = i; } } gap[level[u]]--; if(!gap[level[u]]) return ans; level[u] = minn + 1; gap[level[u]]++; if(u != s) u = e[sta[--top]^1].to; } return ans; } void dfs(int u, int op) { vis[u][op] = 1; for(int i = head[u];i != -1;i = e[i].nxt) { int v = e[i].to; if(op == 0) { if(e[i].cap - e[i].flow && !vis[v][op]) dfs(v, op); } else { if(e[i^1].cap - e[i^1].flow && !vis[v][op]) dfs(v, op); } } } int main() { while(scanf("%d%d%d", &n, &m, &k)) { if(n == 0 && m == 0 && k == 0) break; int s = n + m + 1, t = 0; no = 0; memset(head, -1, sizeof(head)); for(int i = 1;i <= n;i++) add(s, i, INF, -1); for(int i = 1;i <= k;i++) { scanf("%d%d%d", &a, &b, &x); add(a, b, x, i); } int res = sap(s, t, n + m + 2); memset(vis, 0, sizeof(vis)); dfs(s, 0); dfs(t, 1); ans.clear(); for(int i = 0;i < no;i += 2) { int u = e[i].from, v = e[i].to; if(e[i].cap - e[i].flow == 0 && vis[u][0] && vis[v][1]) ans.push_back(e[i].id); } for(int i = 0;i < ans.size();i++) { if(i > 0) printf(" "); printf("%d", ans[i]); } printf("\n"); } return 0; }