1. 程式人生 > >【洛谷P1991】無線通訊網

【洛谷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;
}