POJ - 2349 Arctic Network

https://vjudge.net/problem/POJ-2349

用kruskal,因为允许间接通讯,边权值也是升序排列的,那么去掉前k个大的边,剩下的就是满足通讯至少需要的强度(这个强度说的是两个最远的点之间的,可能小于总的最小连通值,但是允许间接通信)

用prim做的话先得到完整的dis数组,然后给它排序后边的k个用卫星通讯,倒数第k+1个就是至少需要的强度

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=500,M=N*N/2;
int n,m,T,k;
int p[M];
int find(int x)
{
	if(p[x]!=x) p[x]=find(p[x]);
	return p[x];
}
struct node{
	double x,y;
}e[M];

struct edge{
	int u,v;
	double w;
}g[M];
double getd(int i,int j)
{
	double x=e[i].x-e[j].x;
	double y=e[i].y-e[j].y;
	return sqrt(x*x+y*y);
}
bool cmp(struct edge ww,struct edge uu)
{
	return ww.w<uu.w;
}
double  kruskal()
{
	for(int i=1;i<=m;i++) p[i]=i;
	
//	cout<<k<<endl;
	sort(g,g+k,cmp);

	double ans=0;
	int cnt=m;
	for(int i=0;i<k;i++)
	{
		if(cnt<=n) break;  //边值是升序排过序的 ,把最后n个留下直接用卫星信道通讯,那么第n+1大的就是信号强度最低值,这样才能覆盖全场 
		                   //因为允许间接通讯,因此只要通讯器能达到 第n+1大的值即可 
		int a=find(g[i].u),b=find(g[i].v);
		if(a!=b)
		{
			p[a]=b;
			ans=g[i].w;
			cnt--;
		}
	}
	return ans;
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d %d",&n,&m);
		
		for(int i=1;i<=m;i++)
			scanf("%lf %lf",&e[i].x,&e[i].y);
		
		k=0;
		for(int i=1;i<m;i++)
		{
			for(int j=i+1;j<=m;j++)
			{
				double d=getd(i,j);
				g[k].u=i;
				g[k].v=j;
				g[k].w=d;
				k++;	
			} 
		}

		printf("%.2f\n",kruskal());
	}
	return 0;
}
posted @ 2021-07-27 08:58  斯文~  阅读(47)  评论(0)    收藏  举报

你好!