[BZOJ 3007] 拯救小云公主 对偶图
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ 3007] 拯救小云公主 对偶图相关的知识,希望对你有一定的参考价值。
题意
给定 $r, c$ , 以及矩形 $(1, 1), (r, c)$ 内的 $n$ 个点组成的点集 $S$ .
求一条从 $(1, 1)$ 到 $(r, c)$ 的矩形内的路径, 最大化路径到 $S$ 中的点的最小距离.
$n \le 3000$ .
分析
考虑二分答案 $x$ , 判定: 当前有 $n$ 个半径为 $x$ 的圆, 是否能从 $(1, 1)$ 走到 $(r, c)$ .
原图存在路径, 当且仅当对偶图不存在将 $(1, 1)$ 与 $(r, c)$ 割开的边集, 即不存在从左上角到右下角的路径.
实现
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #include <cmath> 6 #define F(i, a, b) for (register int i = (a); i <= (b); i++) 7 #define db double 8 inline int rd(void) { 9 int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; 10 int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; 11 } 12 13 const int N = 3005; 14 15 int n, r, c, x[N], y[N]; 16 int S, T, tot; 17 int f[N]; 18 19 inline int Find(int x) { return f[x] == x ? x : f[x] = Find(f[x]); } 20 inline void Union(int x, int y) { f[Find(x)] = Find(y); } 21 bool Check(db Min) { 22 F(i, 1, tot) f[i] = i; 23 F(i, 1, n) { 24 if (x[i] - Min < 1 || y[i] + Min > c) Union(S, i); 25 if (x[i] + Min > r || y[i] - Min < 1) Union(i, T); 26 } 27 F(i, 1, n) F(j, i+1, n) 28 if (1.0 * (x[i] - x[j]) * (x[i] - x[j]) + 1.0 * (y[i] - y[j]) * (y[i] - y[j]) <= 4 * Min * Min) 29 Union(i, j); 30 return Find(S) != Find(T); 31 } 32 33 int main(void) { 34 #ifndef ONLINE_JUDGE 35 freopen("bzoj3007.in", "r", stdin); 36 #endif 37 38 n = rd(), r = rd(), c = rd(); 39 F(i, 1, n) x[i] = rd(), y[i] = rd(); 40 tot = n, S = ++tot, T = ++tot; 41 42 db L = 0, R = sqrt(1.0 * (r-1) * (r-1) + 1.0 * (c-1) * (c-1)); 43 while (R-L > 1e-4) { 44 db M = (L+R)/2; 45 Check(M) ? L = M : R = M; 46 } 47 printf("%0.2lf\n", L); 48 49 return 0; 50 }
以上是关于[BZOJ 3007] 拯救小云公主 对偶图的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ:4219: 跑得比谁都快 3007: 拯救小云公主