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..
........
........

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 }
posted @ 2017-07-01 09:12  阿波罗2003  阅读(107)  评论(0编辑  收藏