BZOJ 1340: [Baltic2007]Escape逃跑问题
1340: [Baltic2007]Escape逃跑问题
Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 285 Solved: 133
[Submit][Status][Discuss]
Description
战犯们企图逃离监狱,他们详细地计划了如何逃出监狱本身,逃出监狱之后他们希望在附近的一个村子里找到掩护。村子(下图中的B)和监狱(图中的A)中间有一个峡谷,这个峡谷也是有士兵守卫的。守卫峡谷的士兵们坐在岗哨上很少走动,每个士兵的观察范围是100米。士兵所处位置决定了战犯们能否安全通过峡谷,安全通过的条件就是在任何时刻战犯们距离最近的士兵大于100米。 给定峡谷的长、宽和每个士兵在峡谷中的坐标,假定士兵的位置一直保持不变,请你写一个程序计算战犯们能否不被士兵发现,顺利通过峡谷。如果不能,那么战犯们最少需要消灭几个士兵才能安全通过峡谷(无论士兵是否被另一个士兵看到,他都可以被消灭)。
Input
第一行有三个整数L、W和N,分别表示峡谷的长度、宽度和士兵的人数。接下来的N行,每行两个整数Xi和Yi,表示第i个士兵在峡谷的坐标(0 <= Xi <= L, 0 <= Yi <= W),坐标以米为单位,峡谷的西南角坐标为(0, 0),东北角坐标为(L, W),见上图。注意:通过峡谷可以从(0, ys)(0 <= ys <= W)到(L, ye)(0 <= ye <= W),其中ys, ye不一定是整数。
Output
只有一行,为一个整数,即安全通过峡谷需要消灭的士兵的人数,如果不需要消灭任何士兵,则输出0。
Sample Input
130 340 5
10 50
130 130
70 170
0 180
60 260
10 50
130 130
70 170
0 180
60 260
Sample Output
1
HINT
1 <= W <= 50,000 1 <= L <= 50,000 1 <= N <= 250
Source
网络流 最小割
暴力判断两个士兵是否相交就行
1 #include <bits/stdc++.h> 2 3 const int siz = 500005; 4 const int inf = 1000000007; 5 6 int L, W, N; 7 8 int X[siz]; 9 int Y[siz]; 10 11 int S, T; 12 13 int hd[siz]; 14 int nt[siz]; 15 int to[siz]; 16 int fl[siz]; 17 18 inline void add(int u, int v, int f) 19 { 20 static int edge = 0, init = 1; 21 22 if (init)memset(hd, -1, sizeof(hd)), init = 0; 23 24 nt[edge] = hd[u]; to[edge] = v; fl[edge] = f; hd[u] = edge++; 25 nt[edge] = hd[v]; to[edge] = u; fl[edge] = 0; hd[v] = edge++; 26 } 27 28 int dep[siz]; 29 30 inline bool bfs(void) 31 { 32 static int que[siz], l, r; 33 memset(dep, 0, sizeof(dep)); 34 dep[que[l = 0] = S] = r = 1; 35 36 while (l != r) 37 { 38 int u = que[l++], v; 39 40 for (int i = hd[u]; ~i; i = nt[i]) 41 if (fl[i] && !dep[v = to[i]]) 42 dep[que[r++] = v] = dep[u] + 1; 43 } 44 45 return dep[T]; 46 } 47 48 int cur[siz]; 49 50 int dfs(int u, int f) 51 { 52 using std::min; 53 54 if (u == T || !f) 55 return f; 56 57 int used = 0, flow, v; 58 59 for (int i = cur[u]; ~i; i = nt[i]) 60 if (fl[i] && dep[v = to[i]] == dep[u] + 1) 61 { 62 flow = dfs(v, min(fl[i], f - used)); 63 64 used += flow; 65 fl[i] -= flow; 66 fl[i^1] += flow; 67 68 if (fl[i]) 69 cur[u] = i; 70 71 if (f == used) 72 return f; 73 } 74 75 if (!used) 76 dep[u] = 0; 77 78 return used; 79 } 80 81 inline int maxFlow(void) 82 { 83 int maxFlow = 0, newFlow; 84 85 while (bfs()) 86 { 87 memcpy(cur, hd, sizeof(cur)); 88 89 while (newFlow = dfs(S, inf)) 90 maxFlow += newFlow; 91 } 92 93 return maxFlow; 94 } 95 96 inline long long sqr(long long x) 97 { 98 return x * x; 99 } 100 101 inline long long dis(int i, int j) 102 { 103 return sqr(X[i] - X[j]) + sqr(Y[i] - Y[j]); 104 } 105 106 signed main(void) 107 { 108 scanf("%d%d%d", &L, &W, &N); 109 110 for (int i = 1; i <= N; ++i) 111 scanf("%d%d", X + i, Y + i); 112 113 S = 0, T = 2 * N + 1; 114 115 for (int i = 1; i <= N; ++i) 116 { 117 add(i, i + N, 1); 118 if (Y[i] <= 100)add(S, i, inf); 119 if (Y[i] >= W - 100)add(i + N, T, inf); 120 } 121 122 for (int i = 1; i <= N; ++i) 123 for (int j = 1; j <= N; ++j) 124 if (dis(i, j) <= 40000 && i != j) 125 add(i + N, j, inf); 126 127 printf("%d\n", maxFlow()); 128 }
@Author: YouSiki