题意
给出(T)组数据,每组数据第一行给出(s)和(p),分别代表卫星数和哨所数,接下来给出(p)行代表(p)个哨所的坐标。
带有卫星的两个哨所,相互之间可以进行通信;否则 需要俩哨所之间距离小于等于(d)才可以通过无线电通信。
我们需要满足每个哨所之间都有路径,确定最小的(d)。
输出连接网络所需的最小(d),答案保留2个小数点。
PS:我感觉这个英文还是右点难理解,毕竟中文我都看了半天……
思路
这题不难,最小生成树改一下就可以过,但是我写了2h+……
首先我们需要知道一个定理:
如果去掉所有权值大于(d)的边后最小生成树被分割成k个连通分支,图也会被分割成k个连通分支。
所以,由此可得,我们只需要给每个连通支分一个卫星即可,最短距离(D)就变成了去掉 大于(D) 后的 最大的边 ,
即第(X)长的边。
AC代码
#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<list>
#include<stdlib.h>
#include<map>
#include<stack>
#include<stdio.h>
#include<queue>
using namespace std;
typedef long long ll;
#define sc(T) scanf("%d",&T)
#define scc(x,y) scanf("%d %d",&x,&y)
#define pr(T) printf("%d
",T)
#define f(a,b,c) for (int a=b;a<c;a++)
#define ff(a,b,c) for (int a=b;a>c;a--)
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define eps 1e-9
#define PI acos(-1)
const int N=520;
int s,p,f[N];
double book[N*N];
struct node
{
int x,y; //记住!!!改为double结果不对?为啥!?
double w;
} e[N*N],dis[N*N];
int getf(int x)
{
if(x==f[x])
return x;
return f[x]=getf(f[x]);
}
int merge(int x,int y)
{
int t1=getf(x);
int t2=getf(y);
if(t1!=t2)
{
f[t2]=t1;
return 1;
}
return 0;
}
bool cmp1(node x,node y)
{
return x.w<y.w;
}
double d(node a,node b)
{
return sqrt(1.0*(a.x-b.x)*(a.x-b.x)+1.0*(a.y-b.y)*(a.y-b.y));
}
int main()
{
int T;
sc(T);
while(T--)
{
mem(book,0);
scc(s,p);//卫星数、哨所数
for(int i=1; i<=p; i++)
{
f[i]=i;
scc(e[i].x,e[i].y);
}
int k=0;
for(int i=1; i<p; i++)
{
for(int j=i+1; j<=p; j++)
// f(j,0,p)
dis[k].x=i,dis[k].y=j,dis[k++].w=d(e[i],e[j]);
}
sort(dis,dis+k,cmp1);
// for(int i=0;i<k;i++)
// {
// cout<<dis[i].x<<"**"<<dis[i].y<<"***"<<dis[i].w<<endl;
// }
int w=0,cnt=0;
for(int i=0; i<k; i++)
{
if(merge(dis[i].x,dis[i].y))
book[w++]=dis[i].w,cnt++;
if(cnt==p-1)
{
//book[w++]=dis[i].w;
break;
}
}
sort(book,book+w);
// for(int i=0;i<w;i++)
// cout<<book[i]<<"***"<<endl;
printf("%.2f
",book[p-1-s]);//w-p+1//p-1-s
}
return 0;
}