原题:http://acm.hdu.edu.cn/showproblem.php?pid=2732
#include<cstdio> #include<cstring> #include<string> #include<queue> #include<vector> #include<algorithm> #define inf 1e9 using namespace std; const int maxn = 850; const int maxm = 200000; int cas, T = 0, n, d; int num_nodes; char mp1[25][25]; char mp2[25][25]; vector<int>vec[maxn]; struct Edge { int from, to, flow, cap; }edge[maxm*2]; vector<int>G[maxn]; int edgenum; void add(int u, int v, int c) { edge[edgenum].from = u; edge[edgenum].to = v; edge[edgenum].flow = 0; edge[edgenum].cap = c; edgenum++; edge[edgenum].from = v; edge[edgenum].to = u; edge[edgenum].flow = 0; edge[edgenum].cap = 0; edgenum++; G[u].push_back(edgenum-2); G[v].push_back(edgenum-1); } int deep[maxn]; bool vis[maxn]; void BFS(int s, int t) { queue<int>Q; memset(vis, false, sizeof vis); Q.push(t); vis[t] = true; deep[t] = 0; while(!Q.empty()) { int now = Q.front(); Q.pop(); for(int i = 0;i<(int)G[now].size();i++) { int v = edge[G[now][i]].to; if(!vis[v]) { deep[v] = deep[now] + 1; vis[v] = true; Q.push(v); } } } } int gap[maxn]; int cur[maxn]; int front[maxn]; int Augment(int s, int t) { int minflow = inf; int begin = t; while(begin != s) { Edge& e = edge[front[begin]]; minflow = min(minflow, e.cap - e.flow); begin = e.from; } begin = t; while(begin != s) { edge[front[begin]].flow += minflow; edge[front[begin]^1].flow -= minflow; begin = edge[front[begin]].from; } return minflow; } int Maxflow(int s, int t) { int flow = 0; BFS(s, t); memset(gap, 0, sizeof gap); memset(cur, 0, sizeof cur); for(int i = 0;i<num_nodes;i++) gap[deep[i]]++; int begin = s; while(deep[s] < num_nodes) { if(begin == t) { flow += Augment(s, t); begin = s; } bool flag = false; for(int i = cur[begin];i<(int)G[begin].size();i++) { Edge& e = edge[G[begin][i]]; if(e.cap > e.flow && deep[begin] == deep[e.to] + 1) { front[e.to] = G[begin][i]; cur[begin] = i; flag = true; begin = e.to; break; } } if(!flag) { int k = num_nodes-1; for(int i = 0;i<(int)G[begin].size();i++) { Edge& e = edge[G[begin][i]]; if(e.cap > e.flow) k = min(k, deep[e.to]); } if(--gap[deep[begin]] == 0) break; gap[deep[begin] = k+1]++; cur[begin] = 0; if(begin != s) begin = edge[front[begin]].from; } } return flow; } void init() { for(int i = 0;i<num_nodes+2;i++) G[i].clear(); edgenum = 0; memset(deep, 0, sizeof deep); } void Pre_work(int m) { for(int i = 0;i<n;i++) { for(int j = 0;j<m;j++) { if(mp1[i][j] != '0') { vec[i*m+j+1].clear(); bool flag = false; int s = j, e = j; for(int ii = i-d;ii<=i+d;ii++) { if(ii < 0 || ii >= n) continue; for(int jj = s;jj<=e;jj++) { if(jj < 0 || jj >= m) continue; if(ii == i && jj == j) { flag = true; continue; } vec[i*m+j+1].push_back(ii*m+jj+1); } if(flag) s++, e--; else s--, e++; } } } } } int main() { scanf("%d", &cas); while(cas--) { int full_flow = 0; scanf("%d%d", &n, &d); for(int i = 0;i<n;i++) scanf("%s", mp1[i]); for(int i = 0;i<n;i++) scanf("%s", mp2[i]); int m = strlen(mp1[0]); int k = n*m; Pre_work(m); int s = 0, t = 2*k+1; num_nodes = t+1; init(); for(int i = 0;i<n;i++) { for(int j = 0;j<m;j++) { if(mp2[i][j] == 'L') { add(s, i*m+j+1, 1); full_flow++; } if(mp1[i][j] != '0') { int y1 = j + d, y2 = j - d; int x1 = i + d, x2 = i - d; int p = i*m+j+1; if(y2 < 0 || y1 >= m || x2 < 0 || x1 >= n) add(p+k, t, inf); for(int a = 0;a<(int)vec[p].size();a++) { int q = vec[p][a]; add(p+k, q, inf); add(q+k, p, inf); } add(p, p+k, mp1[i][j]-'0'); } } } int flow = Maxflow(s, t); int ans = full_flow - flow; if(ans == 0) printf("Case #%d: no lizard was left behind.\n", ++T); else if(ans == 1) printf("Case #%d: 1 lizard was left behind.\n", ++T); else printf("Case #%d: %d lizards were left behind.\n", ++T, ans); } return 0; }