习题: Star Way To Heaven (最小生成树)

题目

思路

第一眼看到这道题的时候,
最开始想到的是二分&最小生成树
但是想想时间复杂度...\(O(log_{1e6}*k*k)\)
wtf???
但是
我们考虑什么时候才会最优
肯定是两个圆相切的时候才会最好
此时的值就是两个圆相切的距离除以2
所以。。。
我们只需要考虑两颗星星之间的距离,
再跑最小生成树算法即可,
但是如果是kruskal,这又是一个疏密图
总时间复杂度为\(O(log_{k*k}*k*k)\)
瞬间爆炸
所以这道题只能用prim算法
时间复杂度\(O(k*k)\)

代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<climits>
using namespace std;
struct node
{
	double x;
	double y;
}a[6005];
int n,m,k;
bool vis[6005];
double dis[6005];
double solve_dis(int i,int j)
{
	if(i>j)
		swap(i,j);
	if(i==0&&j==k)
		return m;
	if(i==0)
		return a[j].y;
	if(j==k)
		return m-a[i].y;
	return sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
}
int main()
{
	cin>>n>>m>>k;
	for(int i=1;i<=k;i++)
		cin>>a[i].x>>a[i].y;
	k++;
	for(int i=1;i<=k;i++)
		dis[i]=INT_MAX;
	for(int i=1;i<=k;i++)
	{
		double minn=INT_MAX;
		int u=-1;
		for(int j=0;j<=k;j++)
		{
			if(dis[j]<minn&&!vis[j])
			{
				minn=dis[j];
				u=j;
			}
		}
		if(u==-1)
			break;
		vis[u]=1;
		for(int v=1;v<=k;v++)
		{
			if(!vis[v])
			{
				dis[v]=min(dis[v],max(dis[u],solve_dis(u,v)));
			}
		}
	}
	printf("%.9lf",dis[k]/2);
	return 0;
}
posted @ 2019-10-28 21:05  loney_s  阅读(277)  评论(1)    收藏  举报