/*
题解:中文题;
题解:最小生成树+并查集
理解:对于这个题目的题解的话,觉得还是在于将这个坐标转化成序号(1,2,3,…,num)
一直想说的就是题解就是一个思路的问题,对于这个题目的细节还有一些变量还是有必要说下
- 如何判断是不是可以生成最小生成树,其实就是这个n个点 最后你用pre【x】==x,如何超过一个,比如三个,表示的就是从开始到最后连树的时候,这些点就没有用到,那么就不符合题意,不知道你们能不能理解这个判断的过程吖
- 我觉得题解的话,还不如说是我对题目怎么去做,怎么去连树,不同于一般的并查集,这里没有给出编号,就是没有办法去做,我们需要的就是如何去构造这个过程,也就是这个path结构体的赋值的过程
- 可能说了这么多,还是废话,有些初学者还是不懂,我还是把最小生成树和并查集的链接给你们吧
题解:简单的并查集加.....
#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;
}
> 最后还是对初学者有帮助的吖,题解也是我自己的理解,说不上是最详细的并查集和最小生成树的解析