bzoj1066 [SCOI2007]蜥蜴
在一个 \(r\times c\) 的网格地图中有一些石柱,一些石柱上站着一些蜥蜴。 每行每列中相邻石柱的距离为 \(1\) ,蜥蜴的跳跃距离是 \(d\) ,即蜥蜴可以跳到平面距离不超过 \(d\) 的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减 \(1\) (如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为 \(1\) ,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。求最少有多少条蜥蜴无法逃离。
\(r,\ c\leq20, 1\leq d\leq4\)
网络流,最大流
将每个石柱拆为出点和入点,边权为石柱高度。若两个石柱 \(a,\ b\) 能够抵达,那么由 \(a\) 的出点连向 \(b\) 的入点,边权 \(\inf\) 。若石柱 \(a\) 可以跳出网格,那么不必从 \(a\) 向其他石柱连边,直接向虚拟汇点连一条 \(\inf\) 的边。由虚拟源点向所有有蜥蜴的石柱连一条边权为 \(1\) 的边。然后就可以愉悦地跑最大流辣
时间复杂度 \(O(\) 雾,反正 \(EK\) 跑不满 \()\)
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010, maxm = 5e5 + 10, maxt = 25, inf = 1 << 30;
int n, s, t, R, C, D, h[maxn], q[maxn], f[maxn], pre[maxn], mp[maxt][maxt];
struct node {
int x, y, sz, flg;
} a[maxt][maxt];
struct edges {
int nxt, to, w;
edges(int x = 0, int y = 0, int z = 0) : nxt(x), to(y), w(z) {}
} e[maxm];
void addline(int u, int v, int w) {
static int cnt = 1;
e[++cnt] = edges(h[u], v, w), h[u] = cnt;
e[++cnt] = edges(h[v], u, 0), h[v] = cnt;
}
int bfs() {
memset(f, 0, sizeof f);
int l = 1, r = 1;
q[1] = s, f[s] = inf;
while (l <= r) {
int u = q[l++];
for (int i = h[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (!f[v] && e[i].w) {
q[++r] = v, pre[v] = i;
f[v] = min(f[u], e[i].w);
if (v == t) break;
}
}
}
return f[t];
}
int EK() {
int res = 0, tmp;
while ((tmp = bfs())) {
res += tmp;
for (int u = t; u != s; u = e[pre[u] ^ 1].to) {
e[pre[u]].w -= tmp, e[pre[u] ^ 1].w += tmp;
}
}
return res;
}
int main() {
char str[maxt];
int R, C, D, tot = 0;
scanf("%d %d %d", &R, &C, &D);
for (int i = 1; i <= R; i++) {
scanf("%s", str + 1);
for (int j = 1; j <= C; j++) {
a[i][j].sz = str[j] ^ 48;
mp[i][j] = ((i - 1) * C + j) << 1;
}
}
for (int i = 1; i <= R; i++) {
scanf("%s", str + 1);
for (int j = 1; j <= C; j++) {
if (str[j] == 'L') {
a[i][j].flg = 1, tot++;
}
}
}
n = mp[R][C] + 3;
for (int i = 1; i <= R; i++) {
for (int j = 1; j <= C; j++) {
if (!a[i][j].sz) continue;
if (a[i][j].flg) {
addline(n - 1, mp[i][j], 1);
}
if (i <= D || j <= D || R - i < D || C - j < D) {
addline(mp[i][j] | 1, n, inf);
}
addline(mp[i][j], mp[i][j] | 1, a[i][j].sz);
}
}
for (int i = D + 1; i <= R - D; i++) {
for (int j = D + 1; j <= C - D; j++) {
if (!a[i][j].sz) continue;
for (int x = i - D; x <= i + D; x++) {
for (int y = j - D; y <= j + D; y++) {
if (!a[x][y].sz || abs(i - x) + abs(j - y) > D || (i == x && j == y)) continue;
addline(mp[i][j] | 1, mp[x][y], inf);
}
}
}
}
s = n - 1, t = n;
printf("%d", tot - EK());
return 0;
}