POJ 2236 Wireless Network(并查集入门模板题)(详解)

题目链接

题目描述

将所有可以互相连通的电脑放在一个集合中
对于O操作(修电脑),将该电脑与所有已经修好的电脑判断一下,若距离小于D,则合并集合
对于S操作(查询),直接查询两个电脑是否属于同一个集合即可

AC代码:

(函数中没注释的地方,详解见)

#include <stdio.h>
#include <math.h>
const int maxn = 1005;
int f[maxn], h[maxn], flag[maxn], x[maxn], y[maxn];
int n, d, p, q;
char ch; 
void Init() {
    
    
	for(int i=0; i<n; i++) {
    
    
		f[i] = i;
		h[i] = 0;
		flag[i] = 0;  //令标记数组初始为 0,为后续合并做准备 
	}
}
int Find(int i) {
    
    
	return f[i]==i ? f[i] : f[i]=Find(f[i]);
}
void merge(int a, int b) {
    
    
	int fa = Find(a);
	int fb = Find(b);
	if(fa != fb) {
    
    
		if(h[fa] < h[fb]) {
    
    
			f[fa] = fb;	
		} else {
    
    
			f[fb] = fa;	
			if(h[fa] == h[fb]) h[fa]++;
		}
	}
}
void judge(int a, int b) {
    
    
	int fa = Find(a);
	int fb = Find(b);
	//如果两台电脑在同一集合中,则代表可连接 
	if(fa==fb) printf("SUCCESS\n");
	//否则不可连接 
	else printf("FAIL\n");
}

int main(void) {
    
    
	scanf("%d %d", &n, &d);
	Init();  //初始化
	for(int i=1; i<=n; i++) 
		scanf("%d %d", &x[i], &y[i]);
	while(scanf("%c", &ch) != EOF) {
    
    
		if(ch=='O') {
    
    	   //当开机时 
			scanf("%d", &p);
			flag[p] = 1;
			//令标记数组中标号为 p的数值为 1 
			//代表已开机 
			for(int i=1; i<=n; i++) {
    
    
				//找到已开机的电脑 
				if(flag[i]==0) continue;
				double dis = sqrt((x[p]-x[i])*(x[p]-x[i]) + (y[p]-y[i])*(y[p]-y[i]));
				//如果两台电脑的距离小于等于最小距离
				//代表两台电脑可连接,则合并 
				if(dis<=d) merge(p, i);
			}
		} else if(ch=='S') {
    
      //询问两台电脑是否能够连接 
			scanf("%d %d", &p, &q);
			judge(p, q);
		}
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/weixin_51250927/article/details/113621645