typedeflonglong LL; constint N = 1010, M = 20010, INF = 1e8; int n, m, S, T; // f[i] 表示某个边的容量 并不是流量 这里纯粹是因为代码习惯 int h[N], e[M], ne[M], f[M], idx; // d[v] 表示到某个点的增广路径上的最小容量 // pre[v] 表示某个点的来边 这里记录边方便修改流量 int q[N], d[N], pre[N]; bool st[N];
voidadd(int a, int b, int c){ e[idx] = b, ne[idx] = h[a], f[idx] = c, h[a] = idx++; }
boolbfs(){ int hh = 0, tt = 0; memset(st, 0, sizeof st); q[0] = S, st[S] = true, d[S] = INF; while (hh <= tt) { int t = q[hh++]; for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (!st[j] && f[i]) { st[j] = true; d[j] = min(d[t], f[i]); pre[j] = i; if (j == T) returntrue; q[++tt] = j; } } } returnfalse; }
// 洛谷的数据是需要 long long 的,它的每条边都是 2^31 - 1 // 可能存在多条大的流量累加就爆了 int LL EK(){ LL r = 0; while (bfs()) { r += d[T]; for (int i = T; i != S; i = e[pre[i] ^ 1]) f[pre[i]] -= d[T], f[pre[i] ^ 1] += d[T]; } return r; }
intmain(){ memset(h, -1, sizeof h); scanf("%d%d%d%d", &n, &m, &S, &T); while (m--) { int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a, b, c), add(b, a, 0); } printf("%lld\n", EK()); return0; }
constint N = 5010, M = 100010, INF = 0x3f3f3f3f; int h[N], e[M], ne[M], w[M], f[M], idx; // incf: incrase flow int dist[N], pre[N], incf[N]; int n, m, S, T; bool st[N];
voidadd(int a, int b, int c, int d){ e[idx] = b, ne[idx] = h[a], f[idx] = c, w[idx] = d, h[a] = idx++; }
boolSPFA(){ queue<int> q; memset(dist, 0x3f, sizeof dist); // 无需清空 st 数组, 这是 SPFA 的特性 dist[S] = 0, incf[S] = INF, q.push(S); while (q.size()) { int t = q.front(); q.pop(); st[t] = false; for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (f[i] && dist[j] > dist[t] + w[i]) { dist[j] = dist[t] + w[i]; pre[j] = i; incf[j] = min(incf[t], f[i]); if (!st[j]) st[j] = true, q.push(j); } } } return dist[T] != INF; }
voidEK(int& flow, int& cost){ flow = cost = 0; while (SPFA()) { flow += incf[T], cost += dist[T] * incf[T]; for (int i = T; i != S; i = e[pre[i] ^ 1]) f[pre[i]] -= incf[T], f[pre[i] ^ 1] += incf[T]; } }
intmain(){ memset(h, -1, sizeof h); scanf("%d%d%d%d", &n, &m, &S, &T); while (m--) { int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d); add(a, b, c, d), add(b, a, 0, -d); } int flow, cost; EK(flow, cost); printf("%d %d\n", flow, cost); return0; }
无源汇上下界可行流
给定一个包含 n 个点 m 条边的有向图,每条边都有一个流量下界和流量上界。
求一种可行方案使得在所有点满足流量平衡条件的前提下,所有边满足流量限制。
如果存在可行方案,则第一行输出 YES,接下来 m 行,每行输出一个整数,其中第 i 行的整数表示输入的第 i 条边的流量。如果不存在可行方案,直接输出一行 NO。
constint N = 210, M = 21010; int h[N], e[M], ne[M], f[M], g[N], low[M], idx; int n, m, S, T; int cur[N], d[N];
voidadd0(int a, int b, int c){ e[idx] = b, ne[idx] = h[a], f[idx] = c, h[a] = idx++; }
voidadd(int a, int b, int c){ add0(a, b, c), add0(b, a, 0); }
boolbfs(){ queue<int> q; memset(d, -1, sizeof d); d[S] = 0, cur[S] = h[S], q.push(S); while (q.size()) { int t = q.front(); q.pop(); for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (f[i] && d[j] == -1) { d[j] = d[t] + 1; cur[j] = h[j]; if (j == T) returntrue; q.push(j); } } } returnfalse; }
intfind(int u, int lim){ if (u == T) return lim; int r = 0; for (int i = cur[u]; ~i && r < lim; i = ne[i]) { cur[u] = i; int j = e[i]; if (f[i] && d[j] == d[u] + 1) { int t = find(j, min(f[i], lim - r)); r += t, f[i] -= t, f[i^1] += t; if (!t) d[j] = -1; } } return r; }
booldinic(){ while (bfs()) while (find(S, 1e8)); for (int i = h[S]; ~i; i = ne[i]) { if (f[i]) returnfalse; } returntrue; }
intmain(){ memset(h, -1, sizeof h); scanf("%d%d", &n, &m); for (int i = 0; i < m; i++) { int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d); add(a, b, d-c); low[i] = c, g[b] += c, g[a] -= c; } S = n+1, T = n+2; for (int i = 1; i <= n; i++) if (g[i] > 0) add(S, i, g[i]); elseif (g[i] < 0) add(i, T, -g[i]); if (!dinic()) puts("NO"); else { puts("YES"); for (int i = 0; i < m; i++) printf("%d\n", f[i*2+1] + low[i]); } return0; }
constint N = 250, M = 21010, INF = 1e8; int h[N], e[M], ne[M], g[N], f[M], idx; int n, m, S, T; int d[N], cur[N];
voidadd0(int a, int b, int c){ e[idx] = b, ne[idx] = h[a], f[idx] = c, h[a] = idx++; }
voidadd(int a, int b, int c){ add0(a, b, c), add0(b, a, 0); }
boolbfs(){ queue<int> q; memset(d, -1, sizeof d); q.push(S), d[S] = 0, cur[S] = h[S]; while (q.size()) { int t = q.front(); q.pop(); for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (d[j] == -1 && f[i]) { d[j] = d[t] + 1; cur[j] = h[j]; if (j == T) returntrue; q.push(j); } } } returnfalse; }
intfind(int u, int lim){ if (u == T) return lim; int r = 0; for (int i = cur[u]; ~i && r < lim; i = ne[i]) { cur[u] = i; int j = e[i]; if (f[i] && d[j] == d[u] + 1) { int t = find(j, min(f[i], lim - r)); r += t, f[i] -= t, f[i^1] += t; if (!t) d[j] = -1; } } return r; }
intdinic(){ int r = 0, flow; while (bfs()) while (flow = find(S, INF)) r += flow; return r; }
intmain(){ int s, t; memset(h, -1, sizeof h); scanf("%d%d%d%d", &n, &m, &s, &t); for (int i = 0; i < m; i++) { int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d); add(a, b, d-c); g[a] -= c, g[b] += c; } S = n+1, T = n+2; for (int i = 1; i <= n; i++) if (g[i] > 0) add(S, i, g[i]); elseif (g[i] < 0) add(i, T, -g[i]); add(t, s, INF); dinic(); for (int i = h[S]; ~i; i = ne[i]) { if (f[i]) { puts("No Solution"); return0; } } S = s, T = t; int r1 = f[idx-1]; f[idx-1] = f[idx-2] = 0; int r2 = dinic(); printf("%d\n", r1 + r2); return0; }
constint N = 50010, M = 350010, INF = 1e8; int h[N], e[M], ne[M], g[N], f[M], idx; int n, m, S, T; int d[N], cur[N];
voidadd0(int a, int b, int c){ e[idx] = b, ne[idx] = h[a], f[idx] = c, h[a] = idx++; }
voidadd(int a, int b, int c){ add0(a, b, c), add0(b, a, 0); }
boolbfs(){ queue<int> q; memset(d, -1, sizeof d); q.push(S), d[S] = 0, cur[S] = h[S]; while (q.size()) { int t = q.front(); q.pop(); for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (d[j] == -1 && f[i]) { d[j] = d[t] + 1; cur[j] = h[j]; if (j == T) returntrue; q.push(j); } } } returnfalse; }
intfind(int u, int lim){ if (u == T) return lim; int r = 0; for (int i = cur[u]; ~i && r < lim; i = ne[i]) { cur[u] = i; int j = e[i]; if (f[i] && d[j] == d[u] + 1) { int t = find(j, min(f[i], lim - r)); r += t, f[i] -= t, f[i^1] += t; if (!t) d[j] = -1; } } return r; }
intdinic(){ int r = 0, flow; while (bfs()) while (flow = find(S, INF)) r += flow; return r; }
intmain(){ int s, t; memset(h, -1, sizeof h); scanf("%d%d%d%d", &n, &m, &s, &t); for (int i = 0; i < m; i++) { int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d); add(a, b, d-c); g[a] -= c, g[b] += c; } S = n+1, T = n+2; for (int i = 1; i <= n; i++) if (g[i] > 0) add(S, i, g[i]); elseif (g[i] < 0) add(i, T, -g[i]); add(t, s, INF); dinic(); for (int i = h[S]; ~i; i = ne[i]) { if (f[i]) { puts("No Solution"); return0; } } S = t, T = s; int r1 = f[idx-1]; f[idx-1] = f[idx-2] = 0; int r2 = dinic(); printf("%d\n", r1 - r2); return0; }
constint N = 20010, M = 250010, INF = 1e8; int h[N], e[M], ne[M], f[M], idx; int cur[N], d[N]; int n, m, S, T;
voidadd0(int a, int b, int c){ e[idx] = b, ne[idx] = h[a], f[idx] = c, h[a] = idx++; }
voidadd(int a, int b, int c){ add0(a, b, c), add0(b, a, 0); }
boolbfs(){ queue<int> q; memset(d, -1, sizeof d); d[S] = 0, q.push(S), cur[S] = h[S]; while (q.size()) { int t = q.front(); q.pop(); for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (d[j] == -1 && f[i]) { d[j] = d[t] + 1; cur[j] = h[j]; if (j == T) returntrue; q.push(j); } } } returnfalse; }
intfind(int u, int lim){ if (u == T) return lim; int r = 0; for (int i = cur[u]; ~i && r < lim; i = ne[i]) { int j = e[i]; cur[u] = i; if (f[i] && d[j] == d[u] + 1) { int t = find(j, min(f[i], lim - r)); r += t, f[i] -= t, f[i^1] += t; if (!t) d[j] = -1; } } return r; }
intdinic(){ int r = 0, flow; while (bfs()) while (flow = find(S, INF)) r += flow; return r; }
intmain(){ memset(h, -1, sizeof h); int nS, nT; scanf("%d%d%d%d", &n, &m, &nS, &nT); S = n+nS+nT+1, T = S+1; while (nS--) { int iS; scanf("%d", &iS); add(S, iS, INF); } while (nT--) { int iT; scanf("%d", &iT); add(iT, T, INF); } while (m--) { int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a, b, c); } printf("%d\n", dinic()); return0; }