# 網絡流_洛谷P2472

07四川省選

5 8 2
00000000
02000000
00321100
02000000
00000000

…LLLL…

1

100%的數據滿足：1<=r, c<=20, 1<=d<=4

1.注意原始輸入的2個矩陣中間都沒有空格， 全都是字符；
2.題目中跳躍的距離指的是平面距離，是可以直接用數學公式算的；
3.跳躍的判斷條件 if(i + ncu_d > n || i - ncu_d < 1 || j + ncu_d > m || j - ncu_d < 1) add(u, t, inf);
4.題目中要我們輸出的是最少的不能逃脫的蜥蜴的個數，所以最後的答案 = 蜥蜴數 - maxflow；
5.記得在計算蜥蜴數的時候，假如設ans 表示蜥蜴數，要記得給ans 初始化爲0。

AC代碼：

``````#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;

typedef pair<int, int> PII;

const int N = 4000, M = 4e5;
const int inf = 0x3f3f3f3f;

int n, m, ncu_d, s, t, maxflow;
int h[N], w[M], e[M], ne[M], idx;
int g[N][N];
int d[N];
char tmp[N][N], tmp1[N][N];

inline void add(int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
e[idx] = a, w[idx] = 0, ne[idx] = h[b], h[b] = idx ++;
}

inline bool bfs(void) {
memset(d, 0, sizeof d);
queue<int> q;

while(q.size()) q.pop();
d[s] = 1, q.push(s);

while(q.size()) {
int u = q.front(); q.pop();

for(int i = h[u]; i != -1; i = ne[i]) {
int v = e[i];
if(w[i] && !d[v]) {
q.push(v);
d[v] = d[u] + 1;
}
}
}

if(d[t] == 0) return false;
return true;
}

inline int dinic(int u, int flow) {
if(u == t) return flow;

for(int i = h[u]; i != -1; i = ne[i]) {
int v = e[i];
if(d[v] == d[u] + 1 && w[i]) {
int k = dinic(v, min(flow, w[i]));
if(k) {
w[i] -= k;
w[i ^ 1] += k;
return k;
} else d[v] = 0;
}
}

return 0;
}

inline int get_sum(int a, int b, int c, int d) {
return (a - c) * (a - c) + (b - d) * (b - d);
}

int main(void) {
//	freopen("in.txt", "r", stdin);

scanf("%d%d%d", &n, &m, &ncu_d);
memset(h, -1, sizeof h);
s = n * m * 2 + 6, t = s + 1;

//裂點
for(int i = 1; i <= n; i ++) scanf("%s", tmp1[i] + 1);
getchar();
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++) {
g[i][j] = tmp1[i][j] - '0';
if(g[i][j] > 0) {
int u = (i - 1) * m + j;
int v = n * m + (i - 1) * m + j;
}
}

//可以跳躍的點
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
if(g[i][j]) {

int u = n * m + (i - 1) * m + j;

for(int i1 = 1; i1 <= n; i1 ++)
for(int j1 = 1; j1 <= m; j1 ++) {
if(i1 == i && j1 == j) continue;
if(!g[i1][j1]) continue;
if(ncu_d * ncu_d >= get_sum(i, j, i1, j1))
add(u, (i1 - 1) * m + j1, inf);
}

//判斷是否能夠到達匯點
if(i + ncu_d > n  || i - ncu_d < 1 || j + ncu_d > m || j - ncu_d < 1) add(u, t, inf);
}

int ans = 0;
//源點連蜥蜴所在的柱子
for(int i = 1; i <= n; i ++) scanf("%s", tmp[i] + 1);
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
if(tmp[i][j] == 'L') {
int u = (i - 1) * m + j;
ans ++;
}

//跑最大流
int flow;
while(bfs())
while(flow = dinic(s, inf)) maxflow += flow;

printf("%d\n", ans - maxflow);

//	fclose(stdin);
return 0;
}
``````