题解 | #Freckles#

Freckles

https://www.nowcoder.com/practice/41b14b4cd0e5448fb071743e504063cf

// 克鲁斯卡尔算法
// 计算任意两点间的距离,并记录每条边,编号【0 - n-1】
// 对于边的集合进行排序,从小到大
// (克鲁斯卡尔算法)依次遍历所有边,使用并查集判断是否处于同一集合,不属于一个集合就记录该边
// 当连通分量=1时,输出
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;

struct Dot
{
    int id; // 编号,re0
    double x;
    double y;
};

struct Edge
{
    int from;
    int to;
    double length;
};

vector<Dot> dot;
vector<Edge> edge;

// 并查集 start
const int maxn = 100;
int father[maxn];
int height[maxn];
void init(int n)
{
    for (int i = 0; i < n; i++)
    {
        father[i] = i;
        height[i] = 0;
    }
}
int find(int x)
{
    if (x != father[x])
    {
        father[x] = find(father[x]);
    }
    return father[x];
}
void Union(int x, int y)
{
    x = find(x);
    y = find(y);
    if (x != y)
    {
        if (height[x] < height[y])
        {
            father[x] = y;
        }
        else if (height[x] > height[y])
        {
            father[y] = x;
        }
        else
        {
            father[y] = x;
            height[x]++;
        }
    }
}
int countFather(int n)
{
    int count = 0;
    for (int i = 0; i < n; i++)
    {
        if (find(i) == i)
            count++;
    }
    return count;
}
// 并查集 end

bool comp(Edge x,Edge y){
    return x.length<y.length;
}

int n,num_of_edge;//结点数  边数

int main(){
    while (cin>>n)
    {
        if(n==0) break;
        double x,y;
        for(int i=0;i<n;i++){
            cin>>x>>y;
            Dot d;
            d.id=i;  //进入vector顺序即编号,可不用id
            d.x=x;
            d.y=y;
            dot.push_back(d);
        }//处理输入

        //每两个结点构成一条边
        num_of_edge=n*(n-1)/2;
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                Edge e;
                e.from=i;
                e.to=j;
                e.length=sqrt((dot[i].x-dot[j].x)*(dot[i].x-dot[j].x)+(dot[i].y-dot[j].y)*(dot[i].y-dot[j].y));
                edge.push_back(e);
            }
        }
        //对边从小到大排序
        sort(edge.begin(),edge.end(),comp);

        init(n);
        double ans=0;
        for(int i=0;i<edge.size();i++){
            if(find(edge[i].from) != find(edge[i].to)){
                Union(edge[i].from , edge[i].to);
                ans+=edge[i].length;
            }
            if(countFather(n)==1){
                break;
            }
        }//kruskal算法

        printf("%.2f",ans);
    }
}

#2022届毕业生现状#
全部评论

相关推荐

07-03 11:02
中山大学 C++
字节刚oc,但距离九月秋招很近了有两段互联网实习,非腾讯字节。不敢赌转正,现在在纠结去还是不去如果实习俩月离职会有什么后果吗
阿城我会做到的:不去后悔一辈子,能否转正取决于ld的态度,只要他不卡,答辩就是走流程,个人觉得可以冲一把
投递字节跳动等公司10个岗位
点赞 评论 收藏
分享
Southyeung:我说一下我的看法(有冒犯实属抱歉):(1)简历不太美观,给我一种看都不想看的感觉,感觉字体还是排版问题;(2)numpy就一个基础包,机器学习算法是什么鬼?我感觉你把svm那些写上去都要好一点。(2)课程不要写,没人看,换成获奖经历;(3)项目太少了,至少2-3个,是在不行把网上学习的也写上去。
点赞 评论 收藏
分享
湫湫湫不会java:1.在校经历全删了2.。这些荣誉其实也没啥用只能说,要的是好的开发者不是好好学生3.项目五六点就行了,一个亮点一俩行,xxx技术解决,xxx问题带来xxx提升。第一页学历不行,然后啥有价值的信息也没有,到第二页看到项目了,第一个项目九点,第二个项目像凑数的俩点。总体给人又臭又长,一起加油吧兄弟
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
07-03 16:22
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务