hdu 1875题解

/*
题解:中文题;
题解:最小生成树+并查集
理解:对于这个题目的题解的话,觉得还是在于将这个坐标转化成序号(1,2,3,…,num)
一直想说的就是题解就是一个思路的问题,对于这个题目的细节还有一些变量还是有必要说下

  1. 如何判断是不是可以生成最小生成树,其实就是这个n个点 最后你用pre【x】==x,如何超过一个,比如三个,表示的就是从开始到最后连树的时候,这些点就没有用到,那么就不符合题意,不知道你们能不能理解这个判断的过程吖
  2. 我觉得题解的话,还不如说是我对题目怎么去做,怎么去连树,不同于一般的并查集,这里没有给出编号,就是没有办法去做,我们需要的就是如何去构造这个过程,也就是这个path结构体的赋值的过程
  3. 可能说了这么多,还是废话,有些初学者还是不懂,我还是把最小生成树和并查集的链接给你们吧

最小生成树描详见
并查集详解

题解:简单的并查集加.....
#include<bits/stdc++.h>
#define maxn 10005
using namespace std;
int pre[maxn];       //记录的是父亲结点
struct node
{
    int from,to;    //从哪里开始到哪里结束
    double val;     //记录的距离
}path[maxn];
bool cmp(node a,node b)     //cmp排序就是从小到大
{
    return a.val<b.val;
}
void init()
{
    for(int i=1;i<=maxn;i++)      //需要初始化
        pre[i]=i;
}
int Find(int x)                      //Find和join函数是并查集的核心
{
    if(x==pre[x])
        return x;
    return pre[x]=Find(pre[x]);
}
bool join(int x,int y)
{
    int fx=Find(x);
    int fy=Find(y);
    if(fx!=fy)
    {
        pre[fx]=fy;
        return true;            //这个题目的需要
    }
    return false;
}
int main()
{
    int T;
    double xx[maxn],yy[maxn];
    cin>>T;
    while(T--){
            init();
            int n;
            cin>>n;
            for(int i=1;i<=n;i++)
                cin>>xx[i]>>yy[i];
            int num=0;             //记录的是多少的边(其实理解可以连接在一起)
            for(int i=1;i<=n;i++)
                for(int j=i+1;j<=n;j++)
            {
                double dis=sqrt(pow(xx[i]-xx[j],2)+pow(yy[i]-yy[j],2));
                if(dis>=10&&dis<=1000)
                {
                    path[num].from=i;
                    path[num].to=j;
                    path[num++].val=dis;
                }
            }
            sort(path,path+num,cmp);
            double ans=0.0;
            for(int i=0;i<num;i++){
                        if(join(path[i].from,path[i].to))         //判断是不是已经加入一个树里面了
                            ans+=path[i].val;
            }
            int mark=0;                
            int flag=0;
            for(int i=1;i<=n;i++){
                        if(pre[i]==i)                         //这个for函数的作用就是判断是不是全部连通
                            mark++;
                        if(mark>1)
                        {
                            flag=1;
                            break;
                        }
            }
            if(flag)
                printf("oh!\n");
            else
                printf("%.1lf\n",ans*100);
    }
    return 0;
}

> 最后还是对初学者有帮助的吖,题解也是我自己的理解,说不上是最详细的并查集和最小生成树的解析
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值