福州大仙2018年複試上機真題1

一,問題描述

 

二,問題分析

該問題我們採用並查集的數據結構來思考

1.最開始初始化,每個城鎮都是孤立的節點,其父節點就是本身

2.道路相通意味着 兩個節點有道路相連,即屬於同於同一個集合,根據輸入的道路相連情況,依次對其進行 並查集的union() 操作,合併到同一個節點

3.最後通過find()操作依次找到所有城鎮的祖先節點,並存入集合set中,集合的大小即爲城鎮劃分的數量

4.注意:n個城鎮,最少只需要n-1條道路即可相連通

三,代碼解答

#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
using namespace std;

int find(vector<int> res, int num) {				//尋找根節點,返回根節點
	int root = num;
	while (res[root] != root)
		root = res[root];
	return root;
}

void union1(vector<int> &res, int x, int y) {		//把x,y兩個集合合併,y爲x的父節點
	int root1 = find(res, x);
	int root2 = find(res, y);
	if (root1 != root2) {				//根節點相同說明在同一個集合中
		res[root1] = root2;
	}
}

int main() {
	int n, m;			//n城鎮數目,m街道數目
	while (cin >> n >> m) {
		if (m == 0) {
			cout << 0 << endl;
		}
		set<int> res;			//記錄城鎮的集合
		vector<int> towm(n + 1);			//多開闢一位空間,保證下標可以到達n
		for (int i = 0; i < n + 1; i++) {		//並查集的初始化
			towm[i] = i;
		}
		for (int i = 0; i < m; i++) {		//對道路情況進行合併操作
			int a, b;
			cin >> a >> b;
			union1(towm, a, b);
		}
		int root;
		for (int i = 0; i < n+1; i++) {		//得到所有城鎮的根節點,並存入set中
			root = find(towm, i);
			res.insert(root);
		}
		cout <<res.size()-2 << endl;			//res.size()-2  要減去0整個多開闢的空間   n個城鎮最好只要n-1個道路

	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章