题意:在一个平面中,有n台电脑,但是此时所有的电脑都是坏的,给出每台电脑的坐标(x,y)和一个距离d
如果电脑是好的,并且电脑之间的距离小于d,那么这两台电脑就可以联通,电脑可以借助电脑联通,也就是说,如果
a--b b--c 那么可以认为 a--c 。现在给出两种操作, ‘O’ 表示修理某一台电脑,‘S’表示查询 两台电脑是否联通
是 则输出“SUCCESS” 否则输出“FAIL”
思路: 很明显的一个并查集题目,如果两台电脑之间的距离小于d,就认为他们直接有联系,如果两台电脑都是修好的,并且有联系,就认为他们可以联通,把这两台电脑合并集合。查询就直接判断两台电脑是否在一个集合中即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
int n,D;
int par[1005],rk[1005],link[1005][1005],vis[1005]//link记录联系,vis记录是否被修好;
int X[1005],Y[1005];//记录坐标
void init()//初始化
{
for(int i=1;i<=n;i++){
par[i]=i;
rk[i]=0;
}
}
int Find(int x)//查找(最好写成非递归的查找方式)
{
while(x!=par[x])
x=par[x];
return x;
}
void unite(int x,int y)//合并
{
x=Find(x);
y=Find(y);
if(x==y)
return ;
if(rk[x]<rk[y])
par[x]=y;
else{
par[y]=x;
if(rk[x]==rk[y])
rk[x]++;
}
}
bool same(int x,int y)//判断是否处于一个集合
{
return Find(x)==Find(y);
}
int main()
{
memset(link,0,sizeof link);
memset(vis,0,sizeof vis);
scanf("%d%d",&n,&D);
init();
for(int i=1;i<=n;i++)
scanf("%d%d",&X[i],&Y[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
if((X[i]-X[j])*(X[i]-X[j])+(Y[i]-Y[j])*(Y[i]-Y[j])<=D*D){//建立联系
link[i][j]=1;
}
}
char ch[2];
int a,b;
while(~scanf("%s",ch)){
if(ch[0]=='O'){//修好一台电脑,就判断此台电脑是否可以和其他电脑联通
scanf("%d",&a);
vis[a]=1;
for(int i=1;i<=n;i++)
if(vis[i]==true&&i!=a&&link[a][i])
unite(a,i) ;
}
else if(ch[0]=='S'){
scanf("%d%d",&a,&b);
if(same(a,b))
printf("SUCCESS\n");
else
printf("FAIL\n");
}
}
return 0;
}