#10065. 「一本通 3.1 例 2」北极通讯网络

  • 地址:https://loj.ac/problem/10065
  • 思路:
  1. 当正向思考受阻时,逆向思维可能有奇效。
  2. 问题转化为:找到最小的d,使去掉所有权值>d的边之后,联通支的个数<k;
  3. 定理:如果去掉所有权值>d的边之后,最小生成树被分割为k个联通支,则图也被分为k个联通支。
  • 代码:
    #include <bits/stdc++.h>
    using namespace std;
    const int N=505;
    int fa[N],a[N],b[N];
    int n,k,m,cnt;
    double ans[N];
    struct node{
        int x,y;
        double dis;
    }e[N*N];
    double dis(int a,int b,int c,int d){
        return sqrt((a-c)*(a-c)+(b-d)*(b-d));
    }
    int getfa(int q){
        if(fa[q]!=q) fa[q]=getfa(fa[q]);
        return fa[q];
    }
    inline bool cmp(const node&x,const node&y){
        return x.dis<y.dis;
    }
    int main(){
        scanf("%d%d",&n,&k);
        if(k>=n){
            printf("0.00");return 0;    
        }
        for(int i=1;i<=n;i++)fa[i]=i, scanf("%d%d",&a[i],&b[i]);
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
            e[++m]=(node){i,j,dis(a[i],b[i],a[j],b[j])};
        sort(e+1,e+m+1,cmp);
        for(int i=1;i<=m;i++){
            int fu=getfa(e[i].x), fv=getfa(e[i].y);
            if(fu!=fv){
                fa[fu]=fv;
                ans[++cnt]=e[i].dis;
            }
        }
        printf("%.2lf",ans[cnt-k+1]);
        return 0;
    }

     

posted @ 2019-01-25 10:31  jiansong!  阅读(353)  评论(0编辑  收藏  举报