思路: 普通并查集
分析:
1 初始值所有的电脑都是坏的,然后给肯定n个点的坐标,只有距离不大于d的才认为连通的
2 现在给定两种操作,O p表示编号为p的电脑被修好了,S p q询问p q是否是连通的
3 简单的并查集,先预处理出所有的点到其他点的距离,然后每一次修好一个电脑之后就去更新并查集,遇到询问的时候只要判断是否在同一个集合里面即可
代码:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 1010;
struct Node{
int x;
int y;
};
Node node[MAXN];
int n , d;
int father[MAXN];
bool isOk[MAXN];
double dis[MAXN][MAXN];
void init(){
memset(isOk , false , sizeof(isOk));
for(int i = 1 ; i <= n ; i++)
father[i] = i;
for(int i = 1 ; i <= n ; i++){
for(int j = i+1 ; j <= n ; j++){
int tmpx = (node[i].x-node[j].x)*(node[i].x-node[j].x);
int tmpy = (node[i].y-node[j].y)*(node[i].y-node[j].y);
dis[i][j] = dis[j][i] = sqrt(tmpx+tmpy);
}
}
}
int find(int x){
if(father[x] != x)
father[x] = find(father[x]);
return father[x];
}
void solve(int x){
isOk[x] = true;
int fx = find(x);
for(int i = 1 ; i <= n ; i++){
if(isOk[i] && i != x && dis[x][i] <= d){
int fa = find(i);
if(fx != fa)
father[fa] = fx;
}
}
}
int main(){
char ch;
int x , y;
scanf("%d%d" , &n , &d);
for(int i = 1 ; i <= n ; i++)
scanf("%d%d%*c" , &node[i].x , &node[i].y);
init();
while(scanf("%c" , &ch) != EOF){
if(ch == 'O'){
scanf("%d%*c" , &x);
solve(x);
}
else{
scanf("%d%d%*c" , &x , &y);
int fx = find(x);
int fy = find(y);
if(fx == fy)
puts("SUCCESS");
else
puts("FAIL");
}
}
return 0;
}