https://vjudge.net/contest/375481#problem/F
该题是一道并查集的基础板子
总体思路:写出并查集的函数 在修电脑的程序里面对已修过的电脑和输入的本电脑进行集合合并(满足题目的距离条件),这里要遍历一下,集合合并的关键操作p[find(i)]=p[a]
然后查询集合 find[a]==find[b]
注意:不能在外面“o”’质询的外面对电脑进行集合合并,因为只有修过的电脑才有资格连接后能通信 为了简化代码 合并集合写在修电脑的程序里面
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const int N=1100;
int n,d,dis,p[N];
bool st[N];
struct point{
int x,y;
}points[N];
double distance(int tx,int ty)
{
return (points[tx].x-points[ty].x)*(points[tx].x-points[ty].x)+(points[tx].y-points[ty].y)*(points[tx].y-points[ty].y);//sqrt里面要加double
}
int find(int x)
{
if(p[x]!=x) p[x]=find(p[x]);//递归 不断向上找父节点 此处判断条件是if
return p[x];
}
int main()
{
cin>>n>>d;
for(int i=1;i<=n;i++) p[i]=i;//一定要初始化并查集
for(int i=1;i<=n;i++)
{
cin>>points[i].x>>points[i].y;
}
char op;
while(cin>>op)
{
if(op=='O')
{
int a;
cin>>a;
if(!st[a])
{
for(int i=1;i<=n;i++)
{
dis=distance(a,i);
if(st[i] && i!=a && dis<=d*d)
{
p[find(i)]=find(a);//因为质询是实时的 所以只能和已经修好的电脑合并 把i祖宗节点的父节点指向j祖宗节点,就是让j的祖宗变成大祖宗
}
}
st[a]=true;
}
else continue;
}
else
{
int a,b;
cin>>a>>b;
if(find(a)==find(b)) cout<<"SUCCESS"<<endl;
else cout<<"FAIL"<<endl;
}
}
return 0;
}