sgu176 Flow Construction【有源汇有上下界最小流】
同样是模板题。
首先将有源汇转换为无源汇,假设原来的源汇为st,我们加入的源汇为ST,那么我们应该从t到s连一条流量为+∞的边,使原来的st满足收支平衡,退化为普通节点。
分离必要边和其他边,从S到T跑最大流,所有与源或者汇相连的边都流满则证明有解。
去掉t到s容量为+∞的边,去掉必要边,从t到s跑最大流。
把得到的答案相减即可。
如果我们得到的答案是负的,那么说明它内部t到s连成了环,那么我们加上S到s容量为-ans的边,跑S到t的最大流,这样所有的边的流量应该就是0,再加上流量下界即为答案。
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define drep(i, a, b) for (int i = a; i >= b; i--) 4 #define REP(i, a, b) for (int i = a; i < b; i++) 5 #define mp make_pair 6 #define pb push_back 7 #define clr(x) memset(x, 0, sizeof(x)) 8 #define xx first 9 #define yy second 10 using namespace std; 11 typedef long long i64; 12 typedef pair<int, int> pii; 13 const int inf = ~0U >> 1; 14 const i64 INF = ~0ULL >> 1; 15 //****************************** 16 17 const int maxn = 105, maxm = 10105; 18 19 struct Ed { 20 int u, v, nx, c; Ed() {} 21 Ed(int _u, int _v, int _nx, int _c) : 22 u(_u), v(_v), nx(_nx), c(_c) {} 23 } E[maxm << 1]; 24 int G[maxn], edtot = 1; 25 void addedge(int u, int v, int c) { 26 E[++edtot] = Ed(u, v, G[u], c); 27 G[u] = edtot; 28 E[++edtot] = Ed(v, u, G[v], 0); 29 G[v] = edtot; 30 } 31 32 int level[maxn], S, T; 33 bool bfs(int s, int t) { 34 static int que[maxn]; int qh(0), qt(0); 35 clr(level); level[que[++qt] = s] = 1; 36 while (qh != qt) { 37 int x = que[++qh]; if (qh == maxn - 1) qh = 0; 38 for (int i = G[x]; i; i = E[i].nx) if (E[i].c && !level[E[i].v]) { 39 level[que[++qt] = E[i].v] = level[x] + 1; 40 if (qt == maxn - 1) qt = 0; 41 } 42 } 43 return !!level[t]; 44 } 45 int dfs(int u, int rm, int t) { 46 if (u == t) return rm; 47 int rm1 = rm; 48 for (int i = G[u]; i; i = E[i].nx) { 49 if (E[i].c && level[E[i].v] == level[u] + 1) { 50 int flow = dfs(E[i].v, min(E[i].c, rm), t); 51 E[i].c -= flow, E[i ^ 1].c += flow; 52 if ((rm -= flow) == 0) break; 53 } 54 } 55 if (rm1 == rm) level[u] = 0; 56 return rm1 - rm; 57 } 58 59 int l[maxm], in[maxn]; 60 int main() { 61 int n, m; 62 scanf("%d%d", &n, &m); 63 rep(i, 1, m) { 64 int x, y, a, b; scanf("%d%d%d%d", &x, &y, &a, &b); 65 l[i] = a * b; 66 if (b) in[y] += a, in[x] -= a; 67 addedge(x, y, a - a * b); 68 } 69 S = n + 1, T = n + 2; 70 int sum(0); 71 rep(i, 1, n) { 72 if (in[i] > 0) sum += in[i]; 73 if (in[i] > 0) addedge(S, i, in[i]); 74 else addedge(i, T, -in[i]); 75 } 76 addedge(n, 1, 0x3f3f3f3f); 77 while (bfs(S, T)) sum -= dfs(S, 0x3f3f3f3f, T); 78 if (sum) { puts("Impossible"); return 0; } 79 int ans = E[edtot].c; 80 E[edtot].c = E[edtot ^ 1].c = 0; 81 int tmp(0); 82 while (bfs(n, 1)) tmp += dfs(n, 0x3f3f3f3f, 1); 83 ans -= tmp; 84 if (ans < 0) { 85 addedge(S, 1, -ans); 86 while (bfs(S, n)) dfs(S, 0x3f3f3f3f, n); 87 ans = 0; 88 } 89 printf("%d\n", ans); 90 rep(i, 1, m) { 91 printf(i == 1 ? "%d" : " %d", E[(i << 1) ^ 1].c + l[i]); 92 } 93 puts(""); 94 return 0; 95 }