北极网络(Kruskal)

本文介绍了如何使用Kruskal算法解决一个军事通信网络问题。在连接多个北部前哨站时,需要确定最小的通信距离D,使得所有前哨站间都能直接或间接通信。问题涉及到卫星通信和无线电通信,其中卫星通信不受距离限制,无线电通信受限于收发器的功率。通过建立邻接矩阵并应用Kruskal算法求解最小生成树,找到第S+1长的边的长度作为答案。

题目描述

国防部(DND)希望通过无线网络连接几个北部前哨站。

在建立网络时将使用两种不同的通信技术:每个前哨站都有一个无线电收发器,一些前哨站还有一个通信卫星。

任意两个拥有通信卫星的前哨站不论它们的位置如何,都可以通过卫星进行通信。

而如果利用无线电进行通信,则需要两个前哨站的距离不能超过D方可进行通信。

而D的大小取决于收发器的功率,收发器的功率越大,D也就越大,但是需要的成本也就越高。

出于采购和维护的考虑,所有的前哨站都采用相同的收发器,也就是说所有前哨站的无线电通信距离D都是相同的。

你需要确定在保证任意两个前哨站之间都能进行通信(直接或间接)的情况下,D的最小值是多少。

输入格式

第一行包含整数N,表示共有N组测试数据。

每组数据的第一行包含两个整数S和P,其中S为卫星个数,P为前哨站个数。

接下来P行每行包含两个整数x和y,分别表示一个前哨站的横纵坐标。

输出格式

输出一个实数,表示D的最小值,结果保留两位小数。

样例

样例输入

1
2 4
0 100
0 300
0 600
150 750

样例输出

212.13

题解

比较版的题,先邻接矩阵预处理两点见距离,再用Kruskal算法跑最小生成树。因为卫星可以不考虑距离,所以答案为最小生成树第S+1长的边。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int M=1e6+5;
struct edge{
    int u,v;
	double w;
}G[M];
struct node{
    int x,y;
}a[M];
int n,fa[M],cnt,T,p;
double P(int l,int r,int ll,int rr){
	return sqrt((ll-l)*(ll-l)+(rr-r)*(rr-r));
}
void Makeset(){
	for(int i=1;i<=n;i++){
        fa[i]=i;
    }
}
int Findset(int x){
	if(fa[x]!=x){
		fa[x]=Findset(fa[x]);
	}
	return fa[x];
}
void Unionset(int u,int v){
	fa[v]=u;
}
bool cmp(edge e1,edge e2){return e1.w<e2.w;}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d %d",&p,&n);
	    Makeset();
	    cnt=0;
	    for(int i=1;i<=n;i++){
	    	scanf("%d %d",&a[i].x,&a[i].y);
	    	for(int j=1;j<i;j++){
	    		G[++cnt].u=i;G[cnt].v=j;G[cnt].w=P(a[i].x,a[i].y,a[j].x,a[j].y);
	    		G[++cnt].v=i;G[cnt].u=j;G[cnt].w=G[cnt-1].w;
			}
		}
	    sort(G+1,G+cnt+1,cmp);
	    int tot=1,_tot=1;double ans=0;
	    while(_tot<=cnt&&tot<=n-p){
	        int r1=Findset(G[_tot].u);
	        int r2=Findset(G[_tot].v);
	        if(r1!=r2){
	        	ans=max(ans,G[_tot].w);
	            Unionset(r1,r2);
	            tot++;
	        }
	        _tot++;
	    }
	    printf("%.2lf\n",ans);
	}
    return 0;
}

AC!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值