【POJ - 2236】Wireless Network (并查集&详解)

 Wireless Network

POJ - 2236

东南亚发生地震。ACM(亚洲合作医疗队)已经建立了一个无线网络与圈电脑,但一个意外的余震袭击,所有的计算机在网络全部被打破。电脑一个接一个地修好了,网络也渐渐开始运转起来。由于硬件的限制,每台计算机只能直接与距离它不到 d 米的计算机进行通信。但是,每台计算机都可以被视为另外两台计算机之间的通信中介,也就是说,如果计算机A和计算机B可以直接通信,或者计算机C可以与AB进行通信,那么计算机A和计算机B可以进行通信。

在修复网络的过程中,工作人员可以随时进行两种操作,修理一台计算机,或者测试两台计算机是否可以通信。你的工作是回答所有的测试操作。

输入

第一行包含两个整数 N d1 <= N <= 10010 <= d <= 20000)。这里 N 是计算机的数量,从 1 ND 是两台计算机可以直接通信的最大距离。在接下来的 N 行中,每个线包含两个整数 xiyi0 <= xiyi <= 10000),这是 N 计算机的坐标。从 N+1 线到输入结束,有操作,这些操作逐个执行。每行包含以下两种格式之一的操作:1.
"O p"
1 <= p <= N),这意味着修复计算机 p.
2
"S p q" 1 <= p q <= N),这意味着测试计算机 p q 是否可以通信。
输入不会超过 300000
行。

输出

对于每个测试操作,如果两台计算机可以通信,则打印"成功",如果没有,则打印"失败"

示例输入

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

题意描述:给计算机的数量以及两台计算机可通信的最大距离,然后是这些计算机的坐标,O代表修复计算机即某计算机可以和外界连通,S代表测试某两个计算机是否可以连通,可连通输SUCCESS,不可以输出FAIL

解题思路:可以利用并查集,先利用两个数组存每个计算机的坐标,因为并不是每个计算机都可以和其他计算机连通,所以只需要合并可以连通的计算机就行了,可以利用数组标记一下,代表这个计算机可以连通外界;同时计算机连通有距离限制,所以我们还要求可以连通的计算机间的距离,如果它们不超过最大距离,就让它们和其他标记过的计算机合并(也就是前面标记过的可以与其他计算机连通的计算机)。最后判断我们测试的两个计算机是否在一个集合里,此处要求这两个计算机本身必须是可以与外界连通的,然后按情况输出即可。

注意:注意输入格式。
#include<stdio.h>
int x[10500],y[10500],f[10500],book[1050];
//递归找爹  合并联通的计算机 
int getf(int v)
{
	if(f[v]==v)
		return v;
	else
	{
		f[v]=getf(f[v]);
		return f[v]; 
	}
	
} 
	
//合并两个子集
void merge(int v,int u)
{
	int t1,t2;
	t1=getf(v);
	t2=getf(u);
	if(t1!=t2)
	{
		f[t2]=t1;
	}
	return ;
} 

int main(void)
{
	int n,m,d,a,b;
	char s[10];
	scanf("%d %d",&n,&d);//计算机数量,最大距离
	for(int i=1;i<=n;i++)
	{	
		f[i]=i;
		scanf("%d %d",&x[i],&y[i]);	
	}
	
	while(~scanf("%s",s))
	{
		if(s[0]=='O')
		{
			scanf("%d",&m);//哪些计算机可通
			book[m]=1;
			for(int i=1;i<=n;i++)
			{
				if(book[i]==1&&(x[m]-x[i])*(x[m]-x[i])+(y[m]-y[i])*(y[m]-y[i])<=d*d)
					merge(m,i);//合并 
			}
		} 
		
		else//计算某两个是否通
		{
			scanf("%d %d",&a,&b);
			if(getf(a)==getf(b)&&book[a]&&book[b])
				printf("SUCCESS\n");
			else
				printf("FAIL\n"); 
		} 
		 
	}
	
	return 0;
 } 

猜你喜欢

转载自blog.csdn.net/m0_58245389/article/details/120045492