HDU3491 网络流最小割模型

本题是典型的最大流最小割模型,利用最大流等于最小割求解,将每个城市拆成两个点,之间连容量为 ww 的边,注意起点和终点连容量为无穷大的边,然后为了方便,起点连源,终点连汇,容量也为无穷大,城市之间连容量为无穷大的双向边,直接跑最大流即可。

我的代码:

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
120
121
122
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>

using namespace std;

int get() {
char ch;
int flag = 0, tmp = 0;
for (ch = getchar(); ch < 48 || ch > 57; ch = getchar())
if (ch == int('-')) break;
if (ch == int('-'))
flag = 1;
else
tmp = int(ch) - 48;
for (ch = getchar(); 48 <= ch && ch <= 57; ch = getchar())
tmp = tmp * 10 + int(ch) - 48;
return (flag) ? -tmp : tmp;
}

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

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

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];
int u = st;
gap[0] = n;
low[st] = oo;
while (dist[st] < 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 T;
int nc, m, u, v, w, s, t;
T = get();
while (T--) {
nc = get();
n = nc * 2 + 2;
st = 0;
ed = n - 1;
for (int i = 0; i < n; i++) p[i] = -1;
K = 0;
m = get();
s = get();
t = get();
add(st, s, oo);
add(t + nc, ed, oo);
for (int i = 1; i <= nc; i++) {
w = get();
if (i != s && i != t)
add(i, i + nc, w);
else
add(i, i + nc, oo);
}
while (m--) {
u = get();
v = get();
add(u + nc, v, oo);
add(v + nc, u, oo);
}
printf("%d\n", sap());
}
return 0;
}