这类题是典型的Union Find 题目。对于I,直接写出基本的Union 和 Find就行。
对于II,题目要求返回query点的connected components。直接写一个for loop来查找会超时。所以这样的问题,应当首先想到从parent入手。用第二个map,来存每个node的connected components个数。而合并时,应当将parents的connected components个数,加起来。即number of cc (new father) += number of cc (old father)。
class ConnectingGraph2 {
private:
unordered_map<int, int> mp;
unordered_map<int, int> count;
public:
int find_(int i){
int parent = mp[i];
while(parent != mp[parent]){
parent = mp[parent];
}
int next;
while(i != mp[i]){
next = mp[i];
mp[i] = parent;
i = next;
}
return parent;
}
ConnectingGraph2(int n) {
// initialize your data structure here.
for(int i=0; i<n; i++){
mp[i] = i;
count[i] = 1;
}
}
void connect(int a, int b) {
// Write your code here
int a_parent = find_(a), b_parent = find_(b);
if(a_parent != b_parent){
mp[a_parent] = b_parent;
count[b_parent] += count[a_parent];
}
}
int query(int a) {
// Write your code here
int a_parent = find_(a);
return count[a_parent];
}
};
III 更为简单一点,其实就是求(节点数 - 非环边数), 用一个cnt,先union时加一即可。
class ConnectingGraph3 {
private:
unordered_map<int, int> mp;
int cnt;
int num;
public:
int find_(int i){
int parent = mp[i];
while(parent != mp[parent]){
parent = mp[parent];
}
int next;
while(i != mp[i]){
next = mp[i];
mp[i] = parent;
i = next;
}
return parent;
}
void union_(int p, int q){
int p_parent = find_(p), q_parent = find_(q);
if(p_parent != q_parent){
mp[p_parent] = q_parent;
cnt++;
}
}
ConnectingGraph3(int n) {
// initialize your data structure here.
for(int i=1; i<=n; i++){
mp[i] = i;
}
cnt = 0;
num = n;
}
void connect(int a, int b) {
// Write your code here
union_(a, b);
}
int query() {
// Write your code here
return num - cnt;
}
};