卧薪尝胆,厚积薄发。
SDOI2012 拯救小云公主
Date: Sat Oct 27 20:24:59 CST 2018
In Category:
NoCategory
Description:
从
$(1,1)$
走到
$(n,m)$
,不能离开以这两个点为端点的矩形,有
$k$
个怪兽,找一条路径离怪兽距离的最小值最大。
$1\leqslant n\leqslant 3000$
Solution:
题目可以转化为给你
$k$
个圆,为他们确定一个最大的半径,把相交的圆连起来,把和边界相连分别和
$S$
和
$T$
连,使得
$S$
和
$T$
没有被连起来,所以只要两两连边,边权为两点距离
$/2$
,每个点和边界连长为距离的边,做
$kruskal$
,加到
$S$
和
$T$
联通时的边权就是答案。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
#define MAXN 3010
int p,n,m;
struct edges
{
int u,v;
double d;
}es[MAXN * MAXN];
int en = 0;
int x[MAXN],y[MAXN];
double dis(int a,int b)
{
return sqrt(double(x[a] - x[b]) * double(x[a] - x[b]) + double(y[a] - y[b]) * double(y[a] - y[b]));
}
bool cmp_d(edges a,edges b){return a.d < b.d;}
int f[MAXN];
int find(int x){return (x == f[x] ? x : f[x] = find(f[x]));}
int main()
{
scanf("%d%d%d",&p,&n,&m);
for(int i = 1;i <= p;++i)
scanf("%d%d",&x[i],&y[i]);
for(int i = 1;i <= p;++i)
for(int j = 1;j < i;++j)
es[++en] = (edges){i,j,dis(i,j) / 2};
int s = p + 1,t = p + 2;
for(int i = 1;i <= p;++i)
{
es[++en] = (edges){i,s,(double)min(n - x[i],y[i] - 1)};
es[++en] = (edges){i,t,(double)min(x[i] - 1,m - y[i])};
}
sort(es + 1,es + 1 + en,cmp_d);
for(int i = 1;i <= t;++i)f[i] = i;
for(int i = 1;i <= en;++i)
{
if(find(es[i].u) != find(es[i].v))
{
f[find(es[i].u)] = find(es[i].v);
if(find(s) == find(t))
{
printf("%.2lf\n",es[i].d);
break;
}
}
}
return 0;
}
In tag:
图论-kruskal
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡