#include <stdio.h> //节点个数 #define ELEM_C 10 //开始先假设每一个节点都是单独的一棵树,下标(节点)对应的值为它的父节点 //例如:节点0的根节点就是其本身:elems[0] == 0、elems[4] == 4 int elems[ELEM_C] = {0,1,2,3,4,5,6,7,8,9}; //得到当前节点的根节点 int getRoot(int elem){ if (elems[elem] == elem) return elem; else { //压缩路径,每次都在返回根节点前把elem的父节点改成根节点 //这样以后就可以减少递归的深度,从而提高算法效率(其实直接return getRoot(elems[elem]);也可以,只不过递归的深度会越来越大) elems[elem] = getRoot(elems[elem]); return elems[elem]; } } //分别求出两个节点的根,如果不是同一个根节点(即不属于同一个集合),则把其中一个根挂到另一个根下 void merge(int elem_1, int elem_2){ int root_1 = getRoot(elem_1); int root_2 = getRoot(elem_2); if (root_1 != root_2) elems[root_2] = root_1; } void main() { int unionCount, u, v, i, sum=0; //输入节点之间的关联次数 scanf("%d", &unionCount); for (i = 0; i < unionCount; ++i) { //合并树集合 scanf("%d %d", &u, &v); merge(u, v); } //计算出一共有多少个集合 for (i = 0; i < ELEM_C; ++i) { if (elems[i] == i) sum++; } printf("have %d set", sum); }
测试如下: 9 1 2 3 4 5 2 4 6 2 6 8 7 9 7 1 6 2 4 have 3 set