拆点:在这道题里边学会了拆点的思想。简单说就是对于一个点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;
}