并查集练习
题目要求
有N个节点,初始状态互相独立,没有边相连,读入N后,每一行的指令结构为
I 数字1 数字2 // 连接节点1和2
C 数字1 数字2 // 检查节点1和节点2之间有没有路径,若有输出yes,反之输出no
S // 检查网络一共有几片联通片,结束程序
输入样例1:
5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
S
输出样例1:
no
no
yes
There are 2 components.
输入样例2:
5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
I 1 3
C 1 5
S
输出样例2:
no
no
yes
yes
The network is connected.
分析
- 使用一个长度为N的数组存放节点,数组的下标代表节点编号-1,数组的元素有正负两种。若为正,代表这个节点的夫节点的编号-1,若为负,则为根节点,绝对值表示以这个节点为根的树的元素数量。初始状态所有节点置为-1.
- 每次连接两个节点时,将这两个节点所在树的根节点相连(默认输入的两个节点为不同树的节点),因为根节点一旦相连,则这两棵树合二为一,这两个节点自然相连了。要注意这里使用“按秩归并”算法,每次连接始终把节点数量较小的树根指向节点数量较多的树根。
- 查找某个节点的树根时,使用“压缩路径”算法,即每次查找都把当前节点指向树根。
C原码
#include <stdio.h>
#include <stdlib.h>
typedef int SetType;
int FindRoot(SetType S[], int x);
void Union(SetType S[], int x, int y);
void Initial(SetType S[], int sum);
void Check(SetType S[]);
void Connect(SetType S[]);
void Output_Network(SetType S[], int sum);
int main()
{
int sum;
char in;
scanf("%d\n", &sum);
SetType S[sum];
Initial(S, sum);
do
{
scanf("%c ", &in);
switch(in)
{
case 'I' : Connect(S);
break;
case 'C' : Check(S);
break;
case 'S' : Output_Network(S, sum);
break;
}
}while(in != 'S');
return 0;
}
void Initial(SetType S[], int sum)
{
for(int i = 0; i < sum; i ++)
S[i] = -1;
}
int FindRoot(SetType S[], int x)
{
if(S[x] < 0)
return x;
else
return S[x] = FindRoot(S, S[x]);
}
void Union(SetType S[], int root1, int root2)
{
if(S[root1] > S[root2])
{
S[root1] += S[root2];
S[root1] = root2;
}
else
{
S[root2] += S[root1];
S[root2] = root1;
}
}
void Check(SetType S[])
{
int x, y, root1, root2;
scanf("%d %d\n", &x, &y);
root1 = FindRoot(S, x - 1);
root2 = FindRoot(S, y - 1);
if(root1 == root2)
printf("yes\n");
else
printf("no\n");
}
void Connect(SetType S[])
{
int x, y, root1, root2;
scanf("%d %d\n", &x, &y);
root1 = FindRoot(S, x - 1);
root2 = FindRoot(S, y - 1);
if(root1 != root2)
Union(S, root1, root2);
}
void Output_Network(SetType S[], int sum)
{
int counter = 0;
for(int i = 0; i < sum; i ++)
if(S[i] < 0)
counter ++;
if(counter == 1)
printf("The network is connected.\n");
else if(counter > 1)
printf("There are %d components.\n", counter);
}