BZOJ1066: [SCOI2007]蜥蜴
1066: [SCOI2007]蜥蜴
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4506 Solved: 2305
[Submit][Status][Discuss]
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
【题解】
此题每个点有流量限制,可以考虑拆点。
点x拆成x和x'。
有蜥蜴的点x,从S连向x,容量为1
能跳到外部的点x,从x'连向T,容量为INF
能彼此到达的点x,y,从x'连向y,从y'连向x,容量为INF,这样从x走向y,必须先从x走向x'再走向y,限制了点x的流量
然后从x连向x',容量为点x的流量限制
挂了好多细节
写题要专心,一不专心就挂细节
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <cmath> 7 #include <queue> 8 #include <vector> 9 #define min(a, b) ((a) < (b) ? (a) : (b)) 10 #define max(a, b) ((a) > (b) ? (a) : (b)) 11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 12 inline void swap(int &a, int &b) 13 { 14 long long tmp = a;a = b;b = tmp; 15 } 16 inline void read(int &x) 17 { 18 x = 0;char ch = getchar(), c = ch; 19 while(ch < '0' || ch > '9') c = ch, ch = getchar(); 20 while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); 21 if(c == '-')x = -x; 22 } 23 24 const int INF = 0x3f3f3f3f; 25 const int MAXN = 500; 26 const int MAXM = 2000000; 27 28 struct Edge 29 { 30 int u,v,w,nxt; 31 Edge(int _u, int _v, int _w, int _nxt){u = _u;v = _v;w = _w;nxt = _nxt;} 32 Edge(){} 33 }edge[MAXM << 1]; 34 int head[200000], cnt = 1, q[200000], h[200000], ans = 0, S, T; 35 36 inline void insert(int a, int b, int c) 37 { 38 edge[++cnt] = Edge(a,b,c,head[a]); 39 head[a] = cnt; 40 edge[++cnt] = Edge(b,a,0,head[b]); 41 head[b] = cnt; 42 } 43 44 bool bfs() 45 { 46 int he = 0, ta = 1; 47 memset(h, -1, sizeof(h)); 48 q[he] = S, h[S] = 0; 49 while(he < ta) 50 { 51 int now = q[he ++]; 52 for(int pos = head[now];pos;pos = edge[pos].nxt) 53 { 54 int v = edge[pos].v; 55 if(h[v] == -1 && edge[pos].w) 56 { 57 h[v] = h[now] + 1; 58 q[ta ++] = v; 59 } 60 } 61 } 62 return h[T] != -1; 63 } 64 65 int dfs(int x, int f) 66 { 67 if(x == T) return f; 68 int w, used = 0; 69 for(int pos = head[x];pos;pos = edge[pos].nxt) 70 { 71 int v = edge[pos].v; 72 if(h[v] == h[x] + 1) 73 { 74 w = dfs(v, min(f - used, edge[pos].w)); 75 edge[pos].w -= w; 76 edge[pos ^ 1].w += w; 77 used += w; 78 if(used == f) return f; 79 } 80 } 81 if(!used) h[x] = -1; 82 return used; 83 } 84 85 void dinic() 86 { 87 while(bfs()) ans += dfs(S, INF); 88 } 89 90 int r,c,d,g[MAXN][MAXN],x[MAXN << 1],y[MAXN << 1],w[MAXN << 1],tot,t; 91 char s[MAXN][MAXN]; 92 93 int main() 94 { 95 S = 100000, T = 100001; 96 read(r), read(c), read(d); 97 for(register int i = 1;i <= r;++ i) 98 { 99 scanf("%s", s[i] + 1); 100 for(register int j = 1;j <= c;++ j) 101 g[i][j] = s[i][j] - '0'; 102 } 103 for(register int i = 1;i <= r;++ i) 104 scanf("%s", s[i] + 1); 105 for(register int i = 1;i <= r;++ i) 106 for(register int j = 1;j <= c;++ j) 107 { 108 if(s[i][j] == 'L') ++ t; 109 if(g[i][j] > 0) 110 { 111 ++ tot;x[tot] = i, y[tot] = j, w[tot] = g[i][j]; 112 } 113 } 114 for(register int i = 1;i <= tot;++ i) 115 { 116 int tmp = min(x[i], min(y[i], min(r - x[i] + 1, c - y[i] + 1))); 117 if(tmp <= d) 118 insert(i + tot, T, INF); 119 if(s[x[i]][y[i]] == 'L') 120 insert(S, i, 1); 121 insert(i, i + tot, w[i]); 122 } 123 for(register int i = 1;i <= tot;++ i) 124 for(register int j = i + 1;j <= tot;++ j) 125 { 126 if((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]) <= d * d) 127 insert(i + tot, j, INF), insert(j + tot, i, INF); 128 } 129 dinic(); 130 printf("%d", t - ans); 131 return 0; 132 }