原題鏈接
解題思路
並查集的基本實現與應用,外加路徑壓縮和按秩歸併,按秩歸併有按高度歸併和按規模歸併兩種,我更喜歡按規模,就是元素個數嘛。
之前不知道要歸併,以爲路徑壓縮了就完事大吉了,並查集用數組father[]實現,如果father[i] = i表示i是根結點,第一種寫法沒考慮歸併,把father值都插入set中計算連通塊個數。
//僅路徑壓縮
#include<iostream>
#include<set>
using namespace std;
const int maxn = 100010;
int father[maxn];
set<int> res;//記錄根結點,爲了統計有幾個集合
int findFather(int x){
int a = x;
while(x != father[x]){
x = father[x];
}
//記錄根結點,路徑壓縮
int root = x;
while(a != father[a]){
int z = a;
a = father[a];
father[z] = root;
}
return root;
}
void Union(int a, int b){
//按秩歸併,將規模小的集合指向規模大的集合
}
int main(){
char ch;
int n, a, b;
scanf("%d", &n);
//init
for(int i=1; i<=n; i++){
father[i] = i;
}
getchar();
//注意不要讓ch讀成換行
while(scanf("%c", &ch)){
if(ch == 'S')
break;
scanf("%d%d", &a, &b);
getchar();
int faA = findFather(a);
int faB = findFather(b);
if(ch == 'I'){
//如果不屬於一個集合,就合併這兩個元素所在集合
Union(faA, faB);
}
else if(ch == 'C'){
if(faA == faB)
printf("yes\n");
else
printf("no\n");
}
}
//計算有幾個集合
for(int i=1; i<=n; i++){
res.insert(father[i]);
}
if(res.size() == 1){
printf("The network is connected.\n");
}
else{
printf("There are %d components.\n", res.size());
}
return 0;
}
源代碼
要實現按規模歸併,只要重新給根結點的father值賦更合理的值即可,就是該集合中元素個數啦。
//按秩歸併
#include<iostream>
#include<set>
using namespace std;
const int maxn = 100010;
int father[maxn];
//set<int> res;//記錄根結點,爲了統計有幾個集合
int findFather(int x){
int a = x;
while(father[x] > 0){
x = father[x];
}
//記錄根結點的下標,路徑壓縮
int root = x;
while(father[a] > 0){
int z = a;
a = father[a];
father[z] = root;
}
return root;
}
void Union(int a, int b){
//按秩歸併,將規模小的集合指向規模大的集合
if(father[a] < father[b]) {
//b的規模更小 -2 < -1
father[a] += father[b];
father[b] = a;
}
else{
father[b] += father[a];
father[a] = b;
}
}
int main(){
char ch;
int n, a, b;
scanf("%d", &n);
//init
for(int i=1; i<=n; i++){
father[i] = -1;
}
getchar();
//注意不要讓ch讀成換行
while(scanf("%c", &ch)){
if(ch == 'S')
break;
scanf("%d%d", &a, &b);
getchar();
int faA = findFather(a);
int faB = findFather(b);
if(ch == 'I'){
//如果不屬於一個集合,就合併這兩個元素所在集合
Union(faA, faB);
}
else if(ch == 'C'){
if(faA == faB)
printf("yes\n");
else
printf("no\n");
}
}
int res = 0;
//計算有幾個集合
for(int i=1; i<=n; i++){
if(father[i] < 0){
res++;
}
}
// for(int i=1; i<=n; i++){
// res.insert(father[i]);
// }
if(res == 1){
printf("The network is connected.\n");
}
else{
printf("There are %d components.\n", res);
}
return 0;
}