POJ 2236

南亚发生了一次地震。ACM (Asia Cooperated Medical 亚洲联合医疗队) 已经为膝上型电脑搭建了一个无线网络,但受到了一次不可预知的余震攻击,因此网络中的所有电脑都被破坏了。电脑被逐台修复,网络逐步恢复了工作。由于受到硬件的约束,每台电脑只能与距离它不超过 d 米的其它电脑直接通信。但每台电脑可被看作其它两台电脑的通信中转点,也就是说,如果电脑 A 和电脑 B 可以直接通信,或存在一台电脑 C 既可与 A 也可与 B 通信,那么电脑 A 和电脑 B 之间就能够通信。

在处理网络修复的过程中,工作人员们在任何一个时刻,可以执行两种操作:维修一台电脑,或测试两台电脑是否能够通信。请您找出全部的测试操作。

输入

第一行包含了两个整数 N 和 d (1 <= N <= 1001, 0 <= d <= 20000)。此处 N 是电脑的数目,编号从 1 到 N;同时,D 是两台电脑之间能够直接通信的最大距离。接下来的 N 行,每行包含两个整数 xi, yi (0 <= xi, yi <= 10000),表示 N 台电脑的坐标。从第 (N+1) 行到输入结束,是逐一执行的操作,每行包含一个操作,格式是以下两者之一:

  1. “O p” (1 <= p <= N),表示维护电脑 p 。
  2. “S p q” (1 <= p, q <= N),表示测试电脑 p 和 q 是否能够通信。

输入不超过 300000 行。

输出

对于每个测试操作,如果两台电脑能够通信,则打印 “SUCCESS”;否则,打印 “FAIL”。

示例输入

4 1
0 1
0 2
0 3
0 4
O 1
O 2
O 4
S 1 4
O 3
S 1 4

示例输出

FAIL
SUCCESS

题目大意:

给出了一些电脑的坐标,在正常运作的情况下,两台电脑的距离只要在 d 以内就可以正常通信,同时如果a b 能正常通信 b c能正常通信,则a c也可以正常通信。他们初始状态都是坏的。共有两种命令: S x y检测 x和y能否正常通信,O x 修复x电脑。对于每个S命令,输出相应的回答。

解题思路:

基础并查集,起初电脑都是坏的,我们要做的是每修复好一台电脑,就遍历所有修好的电脑,如果他们彼此之间能正常通信就并入同一个集合里,对于S命令,检测一下二者的根节点是否相同即可。开三个数组,一个 f 用于存储根节点,一个 g 存储已经修好的电脑的编号,另一个则用于存储每一台电脑的坐标,之后正常并查集解法就可以。AC代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
using namespace std;
const int N = 1e4+50;
int f[N];
struct node { double x, y; };//存坐标
node a[N];
int g[N];//存已经修好的
int find(int x)//寻根+路径压缩
{
	return f[x] == x ? x : f[x] = find(f[x]);
}
void onion(int x,int y)//合并
{
	int t1 = find(x);
	int t2 = find(y);
	f[t2] = t1;
}
int main()
{
	int n;
	double d;
	cin >> n >> d;
	for (int i = 0; i < n; i ++)
	    cin >> a[i].x >> a[i].y;
	for (int i = 0; i < n; i ++)
	    f[i] = i;
	char ch;
	int good = 0;
	while (cin >> ch)
	{
		if(ch == 'O')
		{
			int h;
			cin >> h;
			h --;
			g[good++] = h;
			for (int i = 0; i < good; i ++)
			{
				double l = sqrt((a[g[i]].x - a[h].x) * (a[g[i]].x - a[h].x) + (a[g[i]].y - a[h].y) * (a[g[i]].y - a[h].y));
				if(l <= d)
				  onion(h, g[i]);
			}
		}
		else
		{
			int p, q;
			cin >> p >> q;
			p --, q --;
			if(find(p) == find(q))
			  cout << "SUCCESS" << endl;
			else
			  cout << "FAIL" << endl;
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Hayasaka/p/14294207.html