[BZOJ1066] [SCOI2007] 蜥蜴 (网络流)
Description
在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃
到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石
柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不
变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个
石柱上。
Input
输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱
,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。
Output
输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。
Sample Input
5 8 2
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........
Sample Output
1
HINT
100%的数据满足:1<=r, c<=20, 1<=d<=4
Source
Solution
类比网络流,每一只蜥蜴的路径就是一条$1$的流,柱子高度减小相当于流量上限减小,然后就可以类比着构出网络流的图:
将每一个柱子拆成两个点,之间连边,流量为这根柱子的高度,借用黄学长的说法,相当于柱子底部到柱子顶部连一条边
超级源点向所有有蜥蜴的柱子连$1$的边,所有可以跳出地图的柱子向超级汇点连$INF$的边(由于单次最大流不超过$400$所以这里边权我写的$400$)
如果一根柱子可以到达另一根,就把该柱子的顶连到另一根的底部,边权$INF$(嗯。。。)
用总蜥蜴数减最大流就是剩下的蜥蜴数
1 #include <bits/stdc++.h> 2 using namespace std; 3 struct edge 4 { 5 int v, w, nxt; 6 }e[30005]; 7 int r, c, fst[805], h[25][25], level[805], q[805], etot = 1; 8 char s[25]; 9 10 void addedge(int u, int v, int w) 11 { 12 e[++etot] = (edge){v, w, fst[u]}, fst[u] = etot; 13 e[++etot] = (edge){u, 0, fst[v]}, fst[v] = etot; 14 } 15 16 int BFS() 17 { 18 int front = 0, back, u; 19 memset(level, 0, sizeof(level)); 20 level[2 * r * c + 1] = 1, q[back = 1] = 2 * r * c + 1; 21 while(front != back) 22 { 23 u = q[++front]; 24 for(int i = fst[u]; i; i = e[i].nxt) 25 if(e[i].w && !level[e[i].v]) 26 { 27 level[e[i].v] = level[u] + 1; 28 q[++back] = e[i].v; 29 } 30 } 31 return level[2 * r * c + 2]; 32 } 33 34 int Dinic(int u, int lim) 35 { 36 int tmp = lim; 37 if(u == 2 * r * c + 2) return lim; 38 for(int i = fst[u]; i; i = e[i].nxt) 39 if(e[i].w && level[e[i].v] == level[u] + 1) 40 { 41 int flow = Dinic(e[i].v, min(tmp, e[i].w)); 42 e[i].w -= flow, e[i ^ 1].w += flow; 43 if(!(tmp -= flow)) break; 44 } 45 if(tmp == lim) level[u] = 0; 46 return lim - tmp; 47 } 48 49 int main() 50 { 51 int d, ans = 0; 52 scanf("%d%d%d", &r, &c, &d); 53 for(int i = 0; i < r; ++i) 54 { 55 scanf("%s", s + 1); 56 for(int j = 1; j <= c; ++j) 57 { 58 h[i + 1][j] = s[j] - 48; 59 addedge(i * c + j, (r + i) * c + j, h[i + 1][j]); 60 } 61 } 62 for(int i = 0; i < r; ++i) 63 { 64 scanf("%s", s + 1); 65 for(int j = 1; j <= c; ++j) 66 if(s[j] == 'L') 67 ++ans, addedge(2 * r * c + 1, i * c + j, 1); 68 } 69 for(int i = 0; i < r; ++i) 70 for(int j = 1; j <= c; ++j) 71 if(h[i + 1][j] && (i < d || i >= r - d || j <= d || j > c - d)) 72 addedge((r + i) * c + j, 2 * r * c + 2, 400); 73 for(int i = d; i < r - d; ++i) 74 for(int j = d + 1; j <= c - d; ++j) 75 if(h[i + 1][j]) 76 for(int k = -d; k <= d; ++k) 77 for(int l = -d; l <= d; ++l) 78 if(h[i + k + 1][j + l] && k * k + l * l <= d * d) 79 addedge((r + i) * c + j, (i + k) * c + j + l, 400); 80 while(BFS()) 81 ans -= Dinic(2 * r * c + 1, 400); 82 printf("%d\n", ans); 83 return 0; 84 }