一,問題描述
二,問題分析
該問題我們採用並查集的數據結構來思考
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;
}