num.10并查集Wireless Network ——POJ - 2236

这道题是[kuangbin带你飞]专题1-23,专题五的第一道题。

题意:

有n台损坏的电脑,现要将其逐台修复,且使其相互恢复通信功能。若两台电脑能相互通信,则有两种情况,一是他们之间的距离小于d,二是他们可以借助都可到达的第三台已修复的电脑。给出所有电脑的坐标位置,对其进行两种可能的操作,O x表示修复第x台,S x y表示判断x y之间能否通信,若能输出SUCCESS,否则输出FALL。

Input:

第一行包含两个整数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行。

Output:

对于每个测试操作,如果两台计算机可以通信,则打印“成功”,否则打印“失败”。

思路

先建一个图,表示电脑都是好的时候能相互通信的网络。
对于维修操作,将被维修的电脑和与其相连的且为好的电脑合并到一个并查集中。
对于查询操作,判断两者是否在一个集合中即可。

#include 
#include 
#include 
#include 
using namespace std;
struct node{
     
	double x;
	double y;//记录电脑的坐标
}arr[1005];
int pre[1005],flag[1005];
char op[2];
double dis(node a,node b){
     
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));//计算两台电脑的距离
}
int n,d,x,y,num;
void init(){
     
	 num=0;
	 memset(flag,0,sizeof(flag));
	 for(int i=1;i<1005;i++)
	 pre[i]=i;//一开始祖先都赋值为自己
}
int find(int x){
     
	if(x==pre[x])
	return x;
	else return pre[x]=find(pre[x]);//并查集查找祖先函数
}
void merge(int x,int y){
     //并查集合并函数
	int fx=find(x);
	int fy=find(y);
	if(fx!=fy) pre[fx]=fy;
}
int main(){
     
	init();
	scanf("%d %d",&n,&d);
	for(int i=1;i<=n;i++){
     
		scanf("%lf %lf",&arr[i].x,&arr[i].y);//先读入n台电脑的坐标
	}
	while(~scanf("%s",op)){
     //不确定有几个操作
		if(op[0]=='O'){
     
			scanf("%d",&x);
			for(int i=0;i<num;i++){
     
				if(dis(arr[flag[i]],arr[x])<=d)//需要每次都判断修好的x号与其他修好的能否通信
				merge(flag[i],x);
			}
			flag[num++]=x;//flag数组里面存的是修好的电脑的序号
		}
		else if(op[0]=='S'){
     
			scanf("%d %d",&x,&y);
			if(find(x)==find(y))
			printf("SUCCESS\n");
			else printf("FAIL\n");
		}
	}
	return 0;
}

你可能感兴趣的:(并查集)