程序设计基础25 并查集(二) 构成并查集的数据每次变更

1013 Battle Over Cities (25 分)

It is vitally important to have all the cities connected by highways in a war. If a city is occupied by the enemy, all the highways from/toward that city are closed. We must know immediately if we need to repair any other highways to keep the rest of the cities connected. Given the map of cities which have all the remaining highways marked, you are supposed to tell the number of highways need to be repaired, quickly.

For example, if we have 3 cities and 2 highways connecting city​1​​-city​2​​ and city​1​​-city​3​​. Then if city​1​​ is occupied by the enemy, we must have 1 highway repaired, that is the highway city​2​​-city​3​​.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 3 numbers N (<1000), M and K, which are the total number of cities, the number of remaining highways, and the number of cities to be checked, respectively. Then M lines follow, each describes a highway by 2 integers, which are the numbers of the cities the highway connects. The cities are numbered from 1 to N. Finally there is a line containing K numbers, which represent the cities we concern.

Output Specification:

For each of the K cities, output in a line the number of highways need to be repaired if that city is lost.

Sample Input:

3 2 3
1 2
1 3
1 2 3

Sample Output:

1
0
0

一,主要思想

    本题主要是求一座城市被占领后,剩下的城市构成的连通块数目减一。在这里求连通块有两种方法,一种是图遍历,另一种是构建并查集。

    这里要先对原始数据进行存储,然后对占领后数据的改动情况再构建并查集,这里如何对原始数据进行存储?答案是二维vector.要注意由于是无向图,二维vector中两个方向都要进行存储。

	for (int i = 0; i < M; i++) {
		scanf("%d %d", &x, &y);
		map[x].push_back(y);
		map[y].push_back(x);
	}

    同时要注意如何排除被占领城市,不仅要在构建并查集的时候排除,也要在计数的时候排除。

	for (int j = 1; j <= N; j++) {
		if (j != checked&&father[j] != checked) {
			vis[findFather(j)] = true;
		}
	}

二,我的代码

#include
#include
using namespace std;
const int max_n = 1010;
int N = 0;
int M = 0;
int K = 0;
int arr[max_n] = { 0 };
int father[max_n] = { 0 };
bool vis[max_n] = { false };
vector map[max_n];
int findFather(int x) {
	int a = x;
	while (x != father[x]) {
		x = father[x];
	}
	while (a != father[a]) {
		int z = a;
		a = father[a];
		father[z] = x;
	}
	return x;
}
void Union(int x, int y) {
	int faA = findFather(x);
	int faB = findFather(y);
	if (faA != faB) {
		father[faA] = faB;
	}
}
void init() {
	for (int i = 1; i <= N; i++) {
		father[i] = i;
		vis[i] = false;
	}
}
int main() {
	scanf("%d %d %d", &N, &M, &K);
	int x = 0, y = 0;
	for (int i = 0; i < M; i++) {
		scanf("%d %d", &x, &y);
		map[x].push_back(y);
		map[y].push_back(x);
	}
	int checked = 0;
	int num_1 = 0;
	for (int i = 0; i < K; i++) {
		scanf("%d", &checked);
		int num = 0;
		init();
		for (int j = 1; j <= N; j++) {
			for (int k = 0; k < map[j].size(); k++) {
				if (j != checked&&map[j][k] != checked) {
					Union(map[j][k], j);
				}
			}
		}
		for (int j = 1; j <= N; j++) {
			if (j != checked&&father[j] != checked) {
				vis[findFather(j)] = true;
			}
		}
		for (int j = 1; j <= N; j++) {
			if (vis[j] == true)num++;
		}
		arr[num_1] = num - 1;
		num_1++;
	}
	for (int i = 0; i < num_1; i++) {
		printf("%d\n", arr[i]);
	}
	return 0;
}

 

你可能感兴趣的:(pat岁月)