洛谷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;
}
posted @ 2020-01-22 15:25  谨川  阅读(151)  评论(0编辑  收藏  举报