题目链接 传送门
题意:就是给你n个点以及它们的坐标,然后就是有两种操作,一种操作是将某一个点恢复,在它周围半径d以内的其他已经恢复的点都与它相连,即将能与它相连的其它连通块都连接起来,另一种操作是询问a,b两点是否属于同一个连通块;
思路:并查集+set优化
简单的并查集
#include <iostream>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
struct Node
{
int x, y, id;
Node(int _x = 0,int _y = 0) : x(_x), y(_y), id(0){}
bool operator < (const Node A) const
{
if(x != A.x) return x < A.x;
return y < A.y;
}
}node[1010];
set <Node> st;
set <Node> :: iterator it;
int vis[1010], pre[1010];
int n, d;
int Find(int x)
{
return pre[x] == x ? x : pre[x] = Find(pre[x]);
}
int main()
{
int a, b;
char c;
memset(vis,-1,sizeof(vis));
scanf("%d%d", &n, &d);
for(int i = 1; i <= n; ++i){
scanf("%d%d", &node[i].x, &node[i].y);
node[i].id = pre[i] = i;
}
getchar();
while(~scanf("%c", &c)){
if(c == 'O'){
scanf("%d", &a);
if(vis[a] == 1) continue;
vis[a] = 1;
for(it = st.lower_bound(Node(node[a].x - d, node[a].y - d)); it != st.end() && node[a].x + d >= it->x ; ++it){
if(vis[it->id] && sqrt(pow(node[a].x - it->x, 2.0) + pow(node[a].y - it->y, 2.0)) <= d)
pre[Find(it->id)] = Find(node[a].id);
}
st.insert(node[a]);
}
else{
scanf("%d%d", &a, &b);
if(vis[a] && vis[b] && Find(a) == Find(b))
printf("SUCCESS\n");
else
printf("FAIL\n");
}
getchar();
}
return 0;
}