【PAT】 A1013 使用并查集解决城市连通问题

/*
 * disjoint_set.cpp
 *
 *  Created on: Jan 28, 2020
 *      Author:
 */

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

int find_root(int *cities_root,int city_id) {
	int city_id_root = city_id;

	//  In this part, recursion is not necessary
	//  can be easily done by while()
	if(cities_root [city_id]!=city_id) {
		while(cities_root [city_id_root]!=city_id_root ) {
			city_id_root = cities_root[city_id_root];
		}
	}else{
		return city_id;
	}

	// compress
	int city_id_tmp = city_id;
	while(cities_root [city_id_tmp]!=city_id_tmp ){
		int city_up_id = cities_root[city_id_tmp];
		city_id_tmp = cities_root[city_up_id];
		cities_root[city_up_id] = city_id_root;
	}
	return city_id_root;
}

// when CityA or CityB is find_root first time, they still use the
// default initialized value, the index of themselves
void union_city(int cityA_id,int cityB_id,int *cities_root){
	int cityA_root = find_root(cities_root,cityA_id);
	int cityB_root = find_root(cities_root,cityB_id);
	if(cityA_root!=cityB_root) {
		// This will connect them together
		// Each time, root is changed, not the leaf
		// leaf might not be processed in the following procedure
		// But once you change the root, in each time of compression
		// In find root, it will be processed
		cities_root [cityA_root] = cityB_root;
	}
}

int main (){
	int city_num, highway_num,city_check;
	scanf ("%d%d%d",&city_num,&highway_num,&city_check);

	//	record the root of city and initialize
	int *cities_root = new int [city_num];
	for (int i = 0; i<city_num;i++) {
		cities_root[i]=i;
	}

	// Allocation of 2D array
	int **city_matrix = new int *[city_num];
	for(int i = 0;i<city_num;i++) {
		city_matrix[i] = new int [city_num]();
	}

	for(int i = 0; i<highway_num;i++) {
		int cityA,cityB;
		scanf ("%d%d",&cityA,&cityB);
		cityA--;
		cityB--;
		//printf("cityA %d cityB %d connected\n",cityA,cityB);
		city_matrix [cityA][cityB] = 1;
	}
	for (int i=0;i<city_check;i++) {
		int city_check_id;
		scanf("%d",&city_check_id);
		city_check_id--;
		 for (int j=0;j<city_num;j++) {
			 for(int k=0;k<city_num;k++){
				 if(city_matrix[j][k]){
					 if((j==city_check_id)||(k==city_check_id)) continue;
					 //printf("check_id %d j %d k %d\n",city_check_id,j,k);
					 union_city(j,k,cities_root);
				 }
			 }
		 }

		 // count the number of connected domain
		int root_count = 0;
		int *visit = new int [city_num]();

		for (int i = 0;i<city_num;i++){
			if (i==city_check_id) continue;

			int city_root = find_root(cities_root ,i);
			//printf("current city check id %d,city %d,root %d\n",city_check_id,i,city_root);
			if (visit[city_root] == false)
				root_count++;
				visit[city_root]=true;
		}

		printf("%d",root_count-1);
		if (i<city_check-1) printf(" ");
		
		// Attention! In each time of queiry
		// the state of array should be recoved!!!
		for (int i = 0; i<city_num;i++) {
			cities_root[i]=i;
			visit[i] = false;
		}
	}

	delete []cities_root;

	for (int i =0;i<city_num;i++) delete [] city_matrix[i];

	delete [] city_matrix;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值