Star Way To Heaven 二分 + 并查集 + Prime

文章目录

  • 题目描述
  • 样例输入输出
  • 题解
  • 参考代码

题目描述

题目描述
小w伤心的走上了 Star way to heaven。
到天堂的道路是一个笛卡尔坐标系上一个n*m的长方形通道(顶点在(0,0)和(n,m)。
小w从最左边任意一点进入,从右边任意一点走到天堂,最左最右的距离为n,上下边界距离为m。
其中长方形有k个Star,每个Star都有一个整点坐标,Star的大小可以忽略不计。
每个Star以及长方形上下两个边缘宇宙的边界都有引力,所以为了成功到达Heaven小w离他们越远越好。
请问小w走到终点的路径上,距离所有星星以及边界的最小距离最大值可以为多少?

输入格式
一行三个整数n,m,k。
接下来k行,每行两个整数xi, yi表示一个点的坐标。

输出格式
一行一个数表示答案。保留到小数点后9位。

数据范围与提示
对于 100% 的数据:k≤6000;n,m≤106

样例输入输出

Sample Input
10 5 2
1 1
2 3
Sample Out普通
1.118033989

题解

对于这道题,我们考虑二分答案。
对于每一个点u,我们以r为半径做圆,如果两个圆的相交,则说明半径为r的取法是不合法的。
那么,我们只需要对于每两个点都建一条边,跑一遍最小生成树,特判一下边界,就好了。
但由于一共有n个点,n2条边,所以,会卡Kruskal,只能用Prime。

参考代码

#include 
#include 
#include 
using namespace std;
#define INf 0x7f7f7f7f

const int N = 6000;
int n, m, k;
double dis[N + 5], x[N + 5], y[N + 5], ans;
bool vis[N + 5];
inline double getDis (const int i, const int j) { 
	return (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]); 
}

int main () {
	scanf ("%d %d %d", &n, &m, &k);
	for (int i = 1; i <= k; ++ i)
		scanf ("%lf %lf", &x[i], &y[i]);
	for (int i = 1; i <= k; ++ i)
		dis[i] = (m - y[i]) * (m - y[i]);
	dis[0] = 1.0 * INf; dis[k + 1] = 1.0 * m * m;
	while (true) {
		int idx = 0;
		for (int i = 1; i <= k + 1; ++ i)
			if (! vis[i] && dis[i] < dis[idx]) 
				idx = i;
		ans = max (ans, dis[idx]);
		if (idx == k + 1)
			break;
		vis[idx] = true;
		for (int i = 1; i <= k; ++ i)
			dis[i] = min ( dis[i], getDis (i, idx) );
		dis[k + 1] = min ( dis[k + 1], y[idx] * y[idx] );
	}
	printf ("%.9lf\n", sqrt ( ans ) / 2);
	return 0;
}

你可能感兴趣的:(Star Way To Heaven 二分 + 并查集 + Prime)