拆点:在这道题里边学会了拆点的思想。简单说就是对于一个点i,将其拆成两个虚点 i 以及 i',然后从 i 连边到 i' ,容量为所要求(本题为调节器)的容量。而对于两个真实点i和j,本该是i连到j,现在将i‘连到j,容量为原先i到j的容量。
#include <stdio.h> #include <string.h> #include <queue> #define min(a,b) (a)<(b)?(a):(b) #define max(a,b) (a)>(b)?(a):(b) #define INF 0x3f3f3f3f using namespace std; const int N = 205; int n, limit, m, A, B, V, sn, tn, line, g[N][N], f[N][N], a[N], p[N]; queue<int>q; void init() { memset(g, 0, sizeof(g)); for (int i = 1; i <= n; i ++) { scanf("%d", &limit); g[i][i + n] = limit; } scanf("%d", &m); while (m --) { scanf("%d%d%d", &A, &B, &V); g[A + n][B] = V; } scanf("%d%d", &sn, &tn); for (int i = 0; i < sn; i ++) { scanf("%d", &line); g[0][line] = INF; } for (int i = 0; i < tn; i ++) { scanf("%d", &line); g[line + n][2 * n + 1] = INF; } } int solve(int s, int t) { init(); int ans = 0; memset(f, 0, sizeof(f)); while (1) { memset(a, 0, sizeof(a)); a[s] = INF; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); for (int v = 1; v <= t; v ++) { if (!a[v] && g[u][v] > f[u][v]) { p[v] = u; q.push(v); a[v] = min(a[u], g[u][v] - f[u][v]); } } } if (!a[t]) break; for (int u = t; u != s; u = p[u]) { f[p[u]][u] += a[t]; f[u][p[u]] -= a[t]; } ans += a[t]; } return ans; } int main() { while (~scanf("%d", &n)) { printf("%d\n", solve(0, 2 * n + 1)); } return 0; }