【题目链接】
http://poj.org/problem?id=2236
题目意思
给1到n编号的电脑,一开始电脑都是坏的,如果两台修好的电脑在d距离内就说明可以通讯,如果A和B能通讯,B和C能通讯,那么久代表A和C能通讯。
现在给你n台电脑的坐标,和2种操作:一种为‘O’+i表示修好电脑i,另一种‘S’+i+j询问i和j是否能通讯。
解题思路
对于这种关系能传递,问是否一起的问题不难想到用并查集,但是一开始电脑全是坏的,所以没修好一台就要遍历一遍之前修好的电脑看是否能通讯。
代码部分
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <string>
#include <map>
using namespace std;
#define LL long long
#define inf 0x3f3f3f3
const int N = 1e4+5;
int pre[N]; ///标记属于哪个集合
int n,d;
int num = 1;
struct point
{
int x, y,i; ///i为点的编号
}a[N],b[N]; ///a保存全部点,b保存修理号的点
int fin (int x) /// 查询集合标记点
{
if (pre[x] != x)
pre[x] = fin(pre[x]); ///用pre[x]等于可以直接压缩路径
return pre[x];
}
void add(int x,int y) ///合并
{
pre[fin(x)] = fin(y); ///把其中一个集合标记点标记成另一个
}
bool dis(point x, point y) ///对比距离
{
int di = (x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y);
return di <= d*d;
}
int main()
{
scanf("%d %d",&n,&d);
for (int i = 1; i <= n; i++)
{
scanf("%d %d",&a[i].x,&a[i].y);
pre[i] = i;
a[i].i = i;
}
char str[3];
while(~scanf("%s",str))
{
int k,l;
if (str[0] == 'O')
{
scanf("%d",&k);
for (int i = 1; i < num; i++) ///没修好一个点遍历已修好的点。
{
if (dis(b[i],a[k]))
{
add(b[i].i,k);
}
}
b[num++] = a[k];
}
else
{
scanf("%d %d",&k,&l);
if (fin(k) == fin(l))
printf("SUCCESS\n");
else printf("FAIL\n");
}
}
return 0;
}