BZOJ 1340: [Baltic2007]Escape逃跑问题

1340: [Baltic2007]Escape逃跑问题

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 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

Sample Output

1

HINT

1 <= W <= 50,000 1 <= L <= 50,000 1 <= N <= 250

Source

 
[Submit][Status][Discuss]

网络流 最小割 

暴力判断两个士兵是否相交就行

  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
", maxFlow());
128 }

@Author: YouSiki

原文地址:https://www.cnblogs.com/yousiki/p/6282498.html