数据结构与算法实验题 9.8 转移炸弹

★实验任务

A国有 N个城市,这些城市编号为 1到 N,有一天,他们调查出恐怖分子在每个城市中都安放了炸弹,于是他们给炸弹也编上了序号,第 i 个城市里的炸弹编号为 i。现在他们想把这些炸弹转移,以便于销毁炸弹。

由于炸弹是通过不同人转移的,所以需要一个指挥部门来记录转移炸弹的信息,以便于有些人要查询这些信息。我们有两个操作:

1.将 a 炸弹目前所在城市中所有的炸弹转移到 b 炸弹所在的城市。

2.询问 a 炸弹目前在哪个城市编号和这个城市中有炸弹个数。

★数据输入

输入第一行包含两个数 N,Q(1<=N<=500000 , 1<=Q<=120000)。分别表示城市的个数和操作数。

接下来有 Q 行,每行表示一个操作,第一种操作输入格式为 1 a b,第二种操作输入格式为 2 a。(1<=a,b<=N)

★数据输出

对于第一个操作,如果两个炸弹在同一个城市里,输出“ERROR”,并不执行此操作。否则执行操作并不输出任何东西。

对于第二种操作,输出一行两个数表示炸弹所在的城市编号和该城市中炸弹个数,用一个空格分开。

输入示例1

3 3
1 1 2
1 3 2
2 2

输出示例1

2 3

输入示例2

3 5
1 1 2
1 2 1
2 1
1 1 3
2 1

输出示例2

ERROR
2 2
3 3

思路:本题用到并查集的思想,将题目给的两个操作看作是并和查,炸弹作为集合,初始时每个炸弹都属于自己的集合。

 代码:

#pragma GCC optimize(2)		//开O2优化 
#include 
#define MAX 500000

int Boomb[MAX]; 

//初始化为-1 
void BoombInit(int size)
{
	for(int i=1; i<=size; i++){
		Boomb[i] = -1;
	}	
	return ; 
}

//查找x所在的城市 
int UFFind(int root)
{ 
	if(Boomb[root]<0)		//如果父结点小于零  那么说明 已经是根节点 那么根就在自己 
		return root; 
	int son, tmp; 
	son = root; 
	while(Boomb[root]>=0){	//寻找城市  
		root = Boomb[root]; 
	} 
	//路径压缩  再从最开始到根  
	while(son!=root){ 
		tmp = Boomb[son]; //原本的上级  
		Boomb[son] = root; //将上级直接指向root  
		son = tmp;  
	}  
	return root;   //返回树根 
}

//a合并到b 
void UFUnion(int a, int b)
{ 
	a = UFFind(a);	//找这俩的爸爸 如果相等 就返回 
	b = UFFind(b);
	if(a==b){
		printf("ERROR\n");
		return ;			//已经在同一座城市里 
	}
	Boomb[b]+=Boomb[a]; 		//此时b要并到a上 那么a 要加上b中的炸弹个数 
	Boomb[a] = b;				//然后再将b的父亲改为a

	return ;		//成功合并 
}
int main(void)
{ 
	int N, Q; 
	int a, b, instruct; 
	scanf("%d %d", &N, &Q); 
	
	BoombInit(N);
	while(Q--){ 
		scanf("%d", &instruct); 
		if(instruct==1){ 
			scanf("%d %d", &a, &b); 
			UFUnion(a, b); 
		}
		else{ 
			scanf("%d", &a); 
			int tmp = UFFind(a);
			printf("%d %d\n", tmp, -Boomb[tmp]); 
		} 
	}
	return 0;
}

 

你可能感兴趣的:(算法,数据结构,算法,ds)