核心思想:
若 a 在以 b 为圆心,d 为半径的圆以内,那么布尔数组 inter[a][b] = inter[b][a] = true,表示二者有潜力相联系。每维修好一台电脑 x ,就遍历所有的电脑,如果第 y 台电脑满足 inter[x][y] == true && x ! = y && 第y台电脑也能运作,就把二者建立在一棵树上。最后访问的时候只用看二者是否在同一棵树上就可以了。🙃
#include <iostream>
#include <cstdio>
#include <cstring>
#define N 1010
using namespace std;
int n, d;
int f[N], x[N], y[N];
bool inter[N][N], work[N]; // inter布尔数组记录两台电脑是否在相互commuinicate的范围内,work数组记录第i个电脑能否工作
int fa, fb, a, b;
int find(int a)
{
if(a != f[a]) f[a] = find(f[a]);
return f[a];
}
inline void merge(int a, int b)
{
fa = find(a), fb = find(b);
if(fa != fb) f[fa] = fb;
}
int main()
{
cin >> n >> d;
for (int i = 1; i <= n; i ++)
{
f[i] = i;
scanf("%d%d", x + i, y + i);
}
for (int i = 1; i <= n; i ++)
{
int X = x[i], Y = y[i];
for (int j = i; j <= n; j ++)
{
int xx = x[j], yy = y[j];
int tmp = (xx - X) * (xx - X) + (yy - Y) * (yy - Y);
if(!inter[i][j] && tmp <= d * d) inter[i][j] = inter[j][i] = true; // 先将在联系范围内的两台电脑标记
}
}
char ch[2];
while(~scanf("%s%d", ch, &a))
{
if(*ch == 'O')
{
work[a] = true;
for (int i = 1; i <= n; i ++)
// 搜索所有的可以相连并且可以工作的电脑,合并成一个连通分支
{
if(work[i] && i != a && inter[i][a]){
merge(a, i);
}
}
}
else
{
scanf("%d", &b);
fa = find(a), fb = find(b);
if(fa != fb) puts("FAIL");
else puts("SUCCESS");
}
}
return 0;
}