POJ1459 多源多汇网络流经典模型

这题是算法导论上的经典模型,将发电站看成源,用户看成汇,这样就形成了多源多汇网络流模型,直接加一个总的源汇即可。

源到发电站的容量为发电站的容量,用户到汇 的容量为用户容量,直接跑最大流即可。

我的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>

using namespace std;

const int MAX = 120;
const int oo = 0x3f3f3f3f;

struct Edge {
int num, ne, cap;
} e[2 * MAX * MAX];
int pre[MAX], pree[MAX], low[MAX], gap[MAX], cur[MAX], p[MAX];
int dist[MAX];
int n, st, ed, K;

int get() {
int ret = 0;
bool flag = false;
char ch;
while ((ch = getchar()) < '0' || ch > '9')
if (ch == '-') break;
if (ch == '-')
flag = true;
else
ret = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') ret = ret * 10 + ch - '0';
return flag ? -ret : ret;
}

void add(const int& u, const int& v, const int& cap) {
e[K].num = v;
e[K].cap = cap;
e[K].ne = p[u];
p[u] = K++;
e[K].num = u;
e[K].cap = 0;
e[K].ne = p[v];
p[v] = K++;
}

int sap() {
int ret = 0;
bool done;
memset(dist, 0, sizeof(dist));
memset(gap, 0, sizeof(gap));
memset(low, 0, sizeof(low));
for (int i = 0; i < n; i++) cur[i] = p[i];
low[st] = oo;
int u = st;
while (dist[u] < n) {
done = true;
for (int i = cur[u]; ~i; i = e[i].ne) {
int v = e[i].num;
cur[u] = i;
if (e[i].cap && dist[u] == dist[v] + 1) {
pre[v] = u;
pree[v] = i;
low[v] = min(low[u], e[i].cap);
u = v;
if (u == ed) {
do {
e[pree[u]].cap -= low[ed];
e[pree[u] ^ 1].cap += low[ed];
u = pre[u];
} while (u != st);
ret += low[ed];
}
done = false;
break;
}
}
if (done) {
gap[dist[u]]--;
if (!gap[dist[u]]) return ret;
dist[u] = n;
cur[u] = p[u];
for (int i = p[u]; ~i; i = e[i].ne) {
if (e[i].cap) dist[u] = min(dist[u], dist[e[i].num] + 1);
}
gap[dist[u]]++;
if (u != st) u = pre[u];
}
}
return ret;
}

int main() {
int nn, np, nc, m;
char ch;
while (~scanf("%d%d%d%d", &nn, &np, &nc, &m)) {
n = nn + 2;
st = nn;
ed = nn + 1;
for (int i = 0; i < n; i++) p[i] = -1;
K = 0;
while (m--) {
while ((ch = getchar()) != '(')
;
int u = get();
int v = get();
int w = get();
add(u, v, w);
}
while (np--) {
int u = get();
int w = get();
add(st, u, w);
}
while (nc--) {
int u = get();
int w = get();
add(u, ed, w);
}
printf("%d\n", sap());
}
return 0;
}