zoukankan      html  css  js  c++  java
  • 洛谷P1991 无线通讯网

    思路:每个哨所都有无线电收发器,故可以看成一颗树 而卫星电话只有m台,为了使只通过无线电收发器通话的哨所之间的距离最短

            先不考虑卫星电话,显然最小生成树最优,距离为最小生成树的最小边

            卫星电话只能连通m个哨所,在最小生成树上可以把这m个哨所看成一个超级源点,此时最小生成树变成了n-m+1个节点,少了m-1条边

            显然为了使距离最短,删去最长的m-1条边

            虽然最长的m-1条边连接的哨所不属于同一连通块,但把最长的m-1条边一端连接的哨所P看成超级源点后,这条边就不需要了 p及其子节点通过超级源点与其他哨所连通

           和loj10066新的开始很像

    注意:1.还好本题m≤n 不然数组下标会越界 n-m<0

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1.3e5+5;
    struct P{
        int x,y;
    }p[505];
    struct E{
        int x,y;//int w
        double w;
    /*    operator <(E a)const{//重载<形参一个  重载()形参两个 [Error] no match for 'operator<' (operand types are 'E' and 'E') 
            return w<a.w;
        }*/ 
    }e[N];//ISO C++ 不允许声明无类型的'operator<'[-fpermissive]
    bool cmp(E a,E b){
        return a.w<b.w;
    }
    /*struct EDGE{
        int next,to,w;
        operator <(EDGE a){
            return w<a.w;
        }
    }edge[N];
    void add(int u,int v){
       edge[++tot].next=head[u];
       edge[tot].to=v;
       edge[tot].w=dist(u,v);
       //head[v]=u;起点的边集 
       head[u]=tot;
    }*/ 
    int tot,head[N],fa[505],rank[505];
    //double d[505][505];邻接矩阵也不行 只能给定起点和终点 得到权值
    double ans[N]; 
    double dist(int i,int j){
        return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));//不需要将P[i].x p[i].y定义为double 函数类型是double 会自动类型转换 
    }
    int find(int x){
        int r=x,now;
        while(x!=fa[x])x=fa[x];
        now=r;
        while(now!=x){
            r=fa[now];
            fa[now]=x;
            now=r;
        }
        return x;//漏了 
    }
    void unio(int x,int y){//union是关键字 
        int fx=find(x),fy=find(y);
        if(rank[fx]<rank[fy])fa[fx]=fy;
        else{
            if(rank[fx]==rank[fy])rank[fx]++;
            fa[fy]=fx;
        }
    }
    int main(){//链式前向型 无法知道起点 
        int n,m,cnt=0;
        cin>>m>>n;
        for(int i=1;i<=n;i++)cin>>p[i].x>>p[i].y,fa[i]=i;
    /*    for(int i=1;i<=n;i++)
         for(int j=i+1;j<=n;j++)
           add(i,j);*/
          for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++){
                e[++tot].x=i;
                e[tot].y=j;
                e[tot].w=dist(i,j);
            }
    //    sort(e+1,e+1+tot);
        sort(e+1,e+1+tot,cmp);
        for(int i=1;i<=tot;i++){
            int fx=find(e[i].x),fy=find(e[i].y);
            if(fx==fy)continue;
            unio(fx,fy);
            ++cnt;
            ans[cnt]=e[i].w;
            if(cnt==n-1)break;
        }
        printf("%.2f",ans[cnt-m+1]);//ans[n-m]
        return 0;
    }
  • 相关阅读:
    python基础4
    python的基础数据类型和编码
    python的if语句和while循环
    java特殊运算符
    深入理解java集合
    python常用模块
    python函数的参数问题
    集合关系之间的运算
    集合
    可变类型与不可变类型
  • 原文地址:https://www.cnblogs.com/wyh447154317/p/12228682.html
Copyright © 2011-2022 走看看