您的位置:首页 > 其它

POJ 2236 Wireless Network

2015-08-19 09:51 316 查看
链接:http://poj.org/problem?id=2236

Wireless Network

Time Limit: 10000MSMemory Limit: 65536K
Total Submissions: 19684Accepted: 8252

Description

An earthquake takes place in Southeast Asia. The ACM (Asia Cooperated Medical team) have set up a wireless network with the lap computers, but an unexpected aftershock attacked, all computers in the network were all broken. The
computers are repaired one by one, and the network gradually began to work again. Because of the hardware restricts, each computer can only directly communicate with the computers that are not farther than d meters from it. But every computer can be regarded
as the intermediary of the communication between two other computers, that is to say computer A and computer B can communicate if computer A and computer B can communicate directly or there is a computer C that can communicate with both A and B.

In the process of repairing the network, workers can take two kinds of operations at every moment, repairing a computer, or testing if two computers can communicate. Your job is to answer all the testing operations.

Input

The first line contains two integers N and d (1 <= N <= 1001, 0 <= d <= 20000). Here N is the number of computers, which are numbered from 1 to N, and D is the maximum distance two computers can communicate directly. In the next
N lines, each contains two integers xi, yi (0 <= xi, yi <= 10000), which is the coordinate of N computers. From the (N+1)-th line to the end of input, there are operations, which are carried out one by one. Each line contains an operation in one of following
two formats:

1. "O p" (1 <= p <= N), which means repairing computer p.

2. "S p q" (1 <= p, q <= N), which means testing whether computer p and q can communicate.

The input will not exceed 300000 lines.

Output

For each Testing operation, print "SUCCESS" if the two computers can communicate, or "FAIL" if not.

Sample Input

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


Sample Output

FAIL
SUCCESS


Source
POJ Monthly,HQM

大意——现在有n台损坏的电脑,目前可以一个一个地进行维修。由于硬件的限制,修好了的电脑想要直接相连,那么它们之间的距离必须小于dist。但是如果A与C连接,C与B又连接,那么A与B就间接连接。在修电脑的过程中,工作者随时可以进行两种操作,修电脑或者是测试两台电脑是否已经连接。你的任务是对于每一次测试,如果成功连接,输出SUCCESS,否则输出FAIL。

思路——经过题目分析,发现这是一道裸的并查集的题。查询两台电脑是否连接就是并查集的查询操作,而将两台电脑连接起来就是合并操作。其中合并操作可以按集合规模进行,而查询操作过程中可以进行路径压缩,路径压缩对于性能是至关重要的。当每次我们修好一台电脑后就可以将它与所能连接到的修好的电脑给连接起来。

复杂度分析——时间复杂度:O(n+n*ɑ(n)),空间复杂度:O(n),ɑ(n)阿克尔曼反函数,n在一定范围内可以认为是常数

附上AC代码:

#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
#include <iomanip>
#include <ctime>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <set>
#include <map>
//#pragma comment(linker, "/STACK:102400000, 102400000")
using namespace std;
typedef unsigned int li;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const double pi = acos(-1.0);
const double e = exp(1.0);
const double eps = 1e-8;
const int maxn = 1005;
int father[maxn]; // 存储父节点
char str[5]; // 键入命令
int n, dist; // 电脑台数以及连接距离限制
struct point
{ // 存储电脑坐标及其状态(0表示未修好,1表示修好)
	int x, y;
	bool flag;
} com[maxn];

inline int square(int x); // 计算平方值
inline int distan(point a, point b); // 计算电脑距离的平方
int find(int x); // 查找父节点并路径压缩
void com_union(int x, int y); // 合并能连接到的电脑

int main()
{
	ios::sync_with_stdio(false);
	int x, y;
	while (~scanf("%d%d", &n, &dist))
	{
		memset(father, -1, sizeof(father)); // 初始化
		dist *= dist; // 距离限制的平方
		for (int i=1; i<=n; i++)
		{
			scanf("%d%d", &com[i].x, &com[i].y);
			com[i].flag = 0; // 初始化
		}
		while (~scanf("%s%d", str, &x))
		{
			if (str[0] == 'O')
			{
				com[x].flag = 1;
				for (int i=1; i<=n; i++) // 找出能连接的电脑
					if (i!=x && com[i].flag &&
						distan(com[x], com[i])<=dist)
						com_union(x, i);
			}
			else
			{
				scanf("%d", &y);
				x = find(x);
				y = find(y); // 找出父节点
				printf(x==y ? "SUCCESS\n" : "FAIL\n"); // 父节点相等,则表明连接好了
			}
		}
	}
	return 0;
}

inline int square(int x)
{
	return (x*x);
}

inline int distan(point a, point b)
{
	return square(a.x-b.x)+square(a.y-b.y);
}

int find(int x)
{
	if (father[x] < 0)
		return x;
	return father[x] = find(father[x]); // 此处即为路径压缩
}

void com_union(int x, int y)
{ // 启发式合并,按规模进行
	x = find(x);
	y = find(y);
	if (x == y)
		return ;
	if (father[x] > father[y])
	{ // 根节点的父节点为负数,绝对值为规模大小
		father[y] += father[x];
		father[x] = y;
	}
	else
	{
		father[x] += father[y];
		father[y] = x;
	}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: