题目链接
题目描述
将所有可以互相连通的电脑放在一个集合中
对于O操作(修电脑),将该电脑与所有已经修好的电脑判断一下,若距离小于D,则合并集合
对于S操作(查询),直接查询两个电脑是否属于同一个集合即可
AC代码:
#include <stdio.h>
#include <math.h>
const int maxn = 1005;
int f[maxn], h[maxn], flag[maxn], x[maxn], y[maxn];
int n, d, p, q;
char ch;
void Init() {
for(int i=0; i<n; i++) {
f[i] = i;
h[i] = 0;
flag[i] = 0; //令标记数组初始为 0,为后续合并做准备
}
}
int Find(int i) {
return f[i]==i ? f[i] : f[i]=Find(f[i]);
}
void merge(int a, int b) {
int fa = Find(a);
int fb = Find(b);
if(fa != fb) {
if(h[fa] < h[fb]) {
f[fa] = fb;
} else {
f[fb] = fa;
if(h[fa] == h[fb]) h[fa]++;
}
}
}
void judge(int a, int b) {
int fa = Find(a);
int fb = Find(b);
//如果两台电脑在同一集合中,则代表可连接
if(fa==fb) printf("SUCCESS\n");
//否则不可连接
else printf("FAIL\n");
}
int main(void) {
scanf("%d %d", &n, &d);
Init(); //初始化
for(int i=1; i<=n; i++)
scanf("%d %d", &x[i], &y[i]);
while(scanf("%c", &ch) != EOF) {
if(ch=='O') {
//当开机时
scanf("%d", &p);
flag[p] = 1;
//令标记数组中标号为 p的数值为 1
//代表已开机
for(int i=1; i<=n; i++) {
//找到已开机的电脑
if(flag[i]==0) continue;
double dis = sqrt((x[p]-x[i])*(x[p]-x[i]) + (y[p]-y[i])*(y[p]-y[i]));
//如果两台电脑的距离小于等于最小距离
//代表两台电脑可连接,则合并
if(dis<=d) merge(p, i);
}
} else if(ch=='S') {
//询问两台电脑是否能够连接
scanf("%d %d", &p, &q);
judge(p, q);
}
}
return 0;
}