bzoj 1066 [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
比较基础(水),按照题目大意,能跳的地方连边,每个点(除了源点和汇点)拆成两个点,中间连一条容量为这个石柱的高度(设置节点容量),有蜥蜴的地方源点向它连边,能够跳出地图的点就向汇点连边。这个网络的最大流表示最大能够逃生的蜥蜴数量,用蜥蜴数量一减就是答案。
Code
1 /** 2 * bzoj 3 * Problem#1066 4 * Accepted 5 * Time:40ms 6 * Memory:1688k 7 */ 8 #include <iostream> 9 #include <cstdio> 10 #include <ctime> 11 #include <cctype> 12 #include <cstring> 13 #include <cstdlib> 14 #include <fstream> 15 #include <sstream> 16 #include <algorithm> 17 #include <map> 18 #include <set> 19 #include <stack> 20 #include <queue> 21 #include <vector> 22 #include <stack> 23 using namespace std; 24 typedef bool boolean; 25 #define inf 0xfffffff 26 #define smin(a, b) a = min(a, b) 27 #define smax(a, b) a = max(a, b) 28 #define max3(a, b, c) max(a, max(b, c)) 29 #define min3(a, b, c) min(a, min(b, c)) 30 template<typename T> 31 inline boolean readInteger(T& u){ 32 char x; 33 int aFlag = 1; 34 while(!isdigit((x = getchar())) && x != '-' && x != -1); 35 if(x == -1) { 36 ungetc(x, stdin); 37 return false; 38 } 39 if(x == '-'){ 40 x = getchar(); 41 aFlag = -1; 42 } 43 for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); 44 ungetc(x, stdin); 45 u *= aFlag; 46 return true; 47 } 48 49 template<typename T>class Matrix{ 50 public: 51 T *p; 52 int lines; 53 int rows; 54 Matrix():p(NULL){ } 55 Matrix(int rows, int lines):lines(lines), rows(rows){ 56 p = new T[(lines * rows)]; 57 } 58 T* operator [](int pos){ 59 return (p + pos * lines); 60 } 61 }; 62 #define matset(m, i, s) memset((m).p, (i), (s) * (m).lines * (m).rows) 63 64 typedef class Edge { 65 public: 66 int end; 67 int next; 68 int flow; 69 int cap; 70 Edge(int end = 0, int next = -1, int flow = 0, int cap = 0):end(end), next(next), flow(flow), cap(cap) { } 71 }Edge; 72 73 typedef class MapManager { 74 public: 75 int ce; 76 vector<Edge> edge; 77 int* h; 78 79 MapManager():ce(0), h(NULL) { } 80 MapManager(int nodes):ce(0) { 81 h = new int[(const int)(nodes + 1)]; 82 memset(h, -1, sizeof(int) * (nodes + 1)); 83 } 84 85 inline void addEdge(int from, int end, int flow, int cap) { 86 edge.push_back(Edge(end, h[from], flow, cap)); 87 h[from] = ce++; 88 } 89 90 inline void addDoubleEdge(int from, int end, int cap) { 91 if(cap == 0) return; 92 // cout << from << "->" << end << "(with the cap " << cap << ")" << endl; 93 addEdge(from, end, 0, cap); 94 addEdge(end, from, cap, cap); 95 } 96 97 Edge& operator [] (int pos) { 98 return edge[pos]; 99 } 100 }MapManager; 101 #define m_begin(g, i) (g).h[(i)] 102 #define m_endpos -1 103 104 typedef class Point { 105 public: 106 int x; 107 int y; 108 Point(int x = 0, int y = 0):x(x), y(y) { } 109 }Point; 110 111 int n, m, r; 112 Matrix<char> mmap; 113 Matrix<char> xiyi; 114 MapManager g; 115 int counter = 0; 116 117 int s, t; 118 int halfsize; 119 120 inline int pos(int x, int y) { return x * m + y + 1; } 121 122 inline void init() { 123 readInteger(n); 124 readInteger(m); 125 readInteger(r); 126 mmap = Matrix<char>(n + 1, m + 1); 127 xiyi = Matrix<char>(n + 1, m + 1); 128 getchar(); 129 for(int i = 0; i < n; i++) { 130 gets(mmap[i]); 131 for(int j = 0; j < m; j++) { 132 mmap[i][j] -= '0'; 133 } 134 } 135 for(int i = 0; i < n; i++) 136 gets(xiyi[i]); 137 } 138 139 const int mov[2][4] = {{1, 0, -1, 0}, {0, 1, 0, -1}}; 140 141 Matrix<boolean> vis; 142 queue<Point> Q; 143 inline void find(Point s) { 144 matset(vis, false, sizeof(boolean)); 145 vis[s.x][s.y] = true; 146 Q.push(s); 147 while(!Q.empty()) { 148 Point e = Q.front(); 149 Q.pop(); 150 for(int i = 0; i < 4; i++) { 151 Point eu(e.x + mov[0][i], e.y + mov[1][i]); 152 if(abs(eu.x - s.x) + abs(eu.y - s.y) > r) continue; 153 if(eu.x < 0 || eu.x >= n) continue; 154 if(eu.y < 0 || eu.y >= m) continue; 155 if(vis[eu.x][eu.y]) continue; 156 Q.push(eu); 157 vis[eu.x][eu.y] = true; 158 if(mmap[eu.x][eu.y]) 159 g.addDoubleEdge(pos(s.x, s.y) + halfsize, pos(eu.x, eu.y), inf); 160 } 161 } 162 } 163 164 inline void init_map() { 165 s = 0, t = n * m + 1; 166 halfsize = n * m + 1; 167 g = MapManager(t * 2); 168 vis = Matrix<boolean>(n + 1, m + 1); 169 for(int i = 0; i < n; i++) { 170 for(int j = 0; j < m; j++) { 171 if((i < r || i >= n - r || j < r || j >= m - r) && mmap[i][j]) g.addDoubleEdge(pos(i, j) + halfsize, t, inf); 172 if(mmap[i][j]) 173 find(Point(i, j)); 174 if(xiyi[i][j] == 'L') 175 g.addDoubleEdge(s, pos(i, j), 1), counter++; 176 } 177 } 178 for(int i = 0; i < n; i++) { 179 for(int j = 0; j < m; j++) { 180 g.addDoubleEdge(pos(i, j), pos(i, j) + halfsize, mmap[i][j]); 181 } 182 } 183 } 184 185 int* dis; 186 boolean* vis1; 187 queue<int> que; 188 inline boolean bfs() { 189 memset(vis1, false, sizeof(boolean) * (2 * t + 3)); 190 que.push(s); 191 vis1[s] = true; 192 dis[s] = 0; 193 while(!que.empty()) { 194 int e = que.front(); 195 que.pop(); 196 for(int i = m_begin(g, e); i != m_endpos; i = g[i].next) { 197 if(g[i].cap == g[i].flow) continue; 198 int eu = g[i].end; 199 if(vis1[eu]) continue; 200 vis1[eu] = true; 201 dis[eu] = dis[e] + 1; 202 que.push(eu); 203 } 204 } 205 return vis1[t]; 206 } 207 208 int *cur; 209 inline int blockedflow(int node, int minf) { 210 if((node == t) || (minf == 0)) return minf; 211 int f, flow = 0; 212 for(int& i = cur[node]; i != m_endpos; i = g[i].next) { 213 int& eu = g[i].end; 214 if(dis[eu] == dis[node] + 1 && g[i].flow < g[i].cap && (f = blockedflow(eu, min(minf, g[i].cap - g[i].flow))) > 0) { 215 minf -= f; 216 flow += f; 217 g[i].flow += f; 218 g[i ^ 1].flow -= f; 219 if(minf == 0) return flow; 220 } 221 } 222 return flow; 223 } 224 225 inline void init_dinic() { 226 vis1 = new boolean[(const int)(2 * t + 3)]; 227 dis = new int[(const int)(2 * t + 3)]; 228 cur = new int[(const int)(2 * t + 3)]; 229 } 230 231 inline int dinic() { 232 int maxflow = 0; 233 while(bfs()) { 234 for(int i = 0; i <= (halfsize << 1); i++) 235 cur[i] = m_begin(g, i); 236 maxflow += blockedflow(s, inf); 237 } 238 return maxflow; 239 } 240 241 inline void solve() { 242 printf("%d\n", counter - dinic()); 243 } 244 245 int main() { 246 init(); 247 init_map(); 248 init_dinic(); 249 solve(); 250 return 0; 251 }