【洛谷P1991】无线通讯网
题目大意:给定一个 N 个顶点的完全图,边有边权,现在要求使得图中所有顶点联通的情况下,第 M-1 大的边最小值是多少。
题解:所有点联通的最小要求是所有点和连接这些点的边构成原图的一棵生成树,那么问题转化成原图的一棵生成树中第 M-1 大边的最小值是多少。可知这是一道类似最小瓶颈树的题目,即:最小生成树的第 M-1 大边一定是所有生成树中最小的。因此,答案转化成原图最小生成树中第 M-1 大边。
代码如下
#include <bits/stdc++.h>
using namespace std;
const int maxn=510;
const int maxx=3e5+10;
double x[maxn],y[maxn],rec[maxn];
int n,m,tot,cnt,f[maxn];
struct edge{
int from,to;
double w;
}e[maxx];
bool cmp(const edge& a,const edge& b){return a.w<b.w;}
inline double get_dis(int i,int j){
return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
int find(int x){
return x==f[x]?x:f[x]=find(f[x]);
}
void read_and_parse(){
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++)scanf("%lf%lf",&x[i],&y[i]),f[i]=i;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
e[++tot].w=get_dis(i,j),e[tot].from=i,e[tot].to=j;
}
void solve(){
sort(e+1,e+tot+1,cmp);
for(int i=1;i<=tot;i++){
int a=find(e[i].from),b=find(e[i].to);
if(a!=b)rec[++cnt]=e[i].w,f[a]=b;
}
printf("%.2lf\n",rec[cnt-m+1]);
}
int main(){
read_and_parse();
solve();
return 0;
}