并查集
题意
若两台修好的计算机之间的距离小于等于d时可以直接通信;
若两个计算机A、B和中间计算机C满足(A和C的距离,B和C的距离小于等于d),则A和B可以通信
O i 表示将i号计算机修好; S i j 问i和j是否能通信
题解
使用并查集。
“O i”: i没有所属集合时(par[i] == i)会将i加入和它相连且已维修节点的所属集合,后续会继续合并i所属集合 和 i相连集合
“S i j” :查看i和j是否属于一个集合
代码
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
const int MAXN = 10010;
int N,d;
struct Point{
int x;
int y;
int par;
};
Point comp[MAXN];
bool repair[MAXN];
int find_root(int x)
{
int r = x;
while(comp[r].par != r)
r = comp[r].par;
int i = x;
while(i != r) // compress the path
{
int t = comp[i].par;
comp[i].par = r;
i = t;
}
return r;
}
void join(int node)
{
repair[node] = true;
for(int i = 1; i <= N; i++)
{
if(i != node && repair[i])
{
double dis = pow(comp[i].x - comp[node].x, 2) + pow(comp[i].y - comp[node].y, 2) ;
if(dis <= d * d)
{
int root1 = find_root(i);
int root2 = find_root(node);
if(root1 != root2)
{
comp[root2].par = root1;
}
}
}
}
}
int main()
{
cin >> N >> d;
for(int i = 1; i <= N; i++)
{
cin >> comp[i].x >> comp[i].y;
comp[i].par = i;
}
memset(repair, false, sizeof(repair));
char temp[MAXN];
while(cin >> temp)
{
switch(temp[0])
{
case 'O':
int opr;
cin >> opr;
join(opr);
break;
case 'S':
int x,y;
cin >> x >> y;
if(find_root(x) == find_root(y))
{
cout << "SUCCESS" <<endl;
}
else
cout << "FAIL" <<endl;
break;
}
}
return 0;
}