题目描述
PIPI国有n个哨所,每个哨所都配置了一台型号相同的无线电通讯设备。设备有一个通讯半径D,如果两个哨站距离超过D,就无法直接通讯。
无线电通讯设备功率越高,通讯半径就越大,但是造价也就越高。为了省钱,PIPI需要确定一个最小的通讯半径D,所有的哨站使用这一型号设备后,任意两个哨站都能进行通讯(直接或间接)。
输入
多组测试用例
第一行为整数n,表示哨所的数目。2<=n<=100。
接下来n行,每行给出一个坐标(x,y),表示第i个哨所的坐标。-50000<=x,y<=50000.
输出
每组数据输出一个实数,表示D的最小值。保留两位小数。
样例输入
4
0 100
0 300
0 600
150 750
样例输出
300.00
方法一:克鲁斯卡尔
#include<bits/stdc++.h>
using namespace std;
int n;
typedef pair<int,int> pr;
pr point[105];
struct node{
int x,y;
double d;
bool operator<(const node &tmp) const{
return d<tmp.d;
}
}E[10003];
double cal(pr a,pr b){
return 1ll*(a.first-b.first)*(a.first-b.first)+1ll*(a.second-b.second)*(a.second-b.second);
}
int father[105];
int _find(int x) {return x==father[x]?x:father[x]=_find(father[x]);}
int main(){
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++){
scanf("%d%d",&point[i].first,&point[i].second);
father[i]=i;
}
int tot=0;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
E[tot++]={i,j,cal(point[i],point[j])};
}
}
double ans=0;
sort(E,E+tot);
for(int i=0;i<tot;i++){
int fa=_find(E[i].x),fb=_find(E[i].y);
if(fa!=fb){
father[fa]=fb;
ans=E[i].d;
}
}
printf("%.2f\n",sqrt(ans));
}
}
方法二:普里姆
#include <bits/stdc++.h>
using namespace std;
int n;
const int INF=1e9;
double mp[105][105];
double x[105],y[105];
double dis[105];
bool vis[105];
double sum;
void prim() ///prim求最小生成树
{
sum=0;
for(int i=1; i<n; i++){
dis[i]=mp[0][i];
}
vis[0]=1;
for(int i=1; i<n; i++)
{
double minn=INF;
int minid;
for(int j=1; j<n; j++)
{
if(!vis[j]&&dis[j]<minn)
{
minn=dis[j];
minid=j;
}
}
sum=max(sum,minn);
vis[minid]=1;
for(int j=1; j<n; j++)
{
if(!vis[j]&&dis[j]>mp[minid][j])
{
dis[j]=mp[minid][j];
}
}
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(mp,0,sizeof(mp));
memset(vis,0,sizeof(vis));
for(int i=0; i<n; i++)
{
scanf("%lf%lf",&x[i],&y[i]);
}
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
mp[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); ///建图
}
}
prim();
printf("%.2lf\n",sum);
}
return 0;
}