pku2236(Wireless Network)

这题,额,思路很好理解,说难其实也不难,代码也很好实现,就是慢了一点,不知道大牛是怎么过的,十分的好奇ing

//题意:题目给出 n 台电脑,距离 d,和各台电脑的坐标(x,y)。电脑要通信要满足两个条件:
// 1 电脑被修好,2 电脑之间的距离不超过距离 d 。输入 O p 时代表电脑 p 被修好,输入 S p q 时
//代表测试电脑 p 与 q 之间是否可以通信。
//思路:用到并查集。如果修好的电脑和已经被修好的电脑之间的距离小于 d ,则合并。
//最后判断两台电脑是否可以通信就通过判断电脑是否被修好,根结点是否相等。

#include<stdio.h>
#include<math.h>
#define MAXN 1010
int f[MAXN],k[MAXN],n,d;
//f[]用来存在父节点,k[]用来表示该节点是否已经被修好
struct node
{
	int x,y;
}cor[MAXN];
int find(int x)
{
	if(x!=f[x])
		f[x]=find(f[x]);
	return f[x];
}
void Union(int x,int y)
{
	int a=find(x);
	int b=find(y);
	if(a!=b)
		f[a]=b;
}//合并
int test(int a,int b)//判定距离是否小于d
{
	int l;
	l=((cor[a].x-cor[b].x)*(cor[a].x-cor[b].x)+(cor[a].y-cor[b].y)*(cor[a].y-cor[b].y));
	if(l<=d)
		return 1;
	else return 0;
}
int main()
{
	int i,o=0,a,b;
	char ch[2];
	scanf("%d %d",&n,&d);
	d=d*d;
	for(i=1;i<=n;i++)
	  scanf("%d %d",&cor[i].x,&cor[i].y);
	for(i=1;i<=n;i++)//初始化
	{
		f[i]=i;
		k[i]=0;
	}
	while(scanf("%s",ch)!=EOF)
	{
		if(ch[0]=='O')
		{
			o++;
			scanf("%d",&a);
			if(o==1)
			{
				k[a]=1;continue;
			}//这里第一个修理的就不用合并了吧,避免了一个循环,不过也快不了多少本身
			else 
			{
				k[a]=1;
				for(i=1;i<=n;i++)
				{
					if(k[i]&&test(i,a))//该点已修好,且距离符合要求,则合并
						Union(i,a);
				}
			}
		}
		else 
		{
			scanf("%d %d",&a,&b);
			if(test(a,b)|| (find(a)==find(b)))//直接连接符合要求,或者已经合并到一起
				printf("SUCCESS\n");
			else 
				printf("FAIL\n");
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/nanke/p/2038633.html