1 /** 2 并查集定义: 3 并查集是一种树形数据结构,用于实现如确定某个集合含有哪些元素、判断 4 某两个元素是否存在于同一个集合中、求集合中元素的数量等问题。 5 并查集主要操作: 6 (1)合并两个不相交的集合; 7 (2)判断两个元素是否属于同一集合。 8 9 题目描述: 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直 10 接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通( 11 但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设 12 多少条道路? 13 输入: 14 测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别 15 是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出 16 一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从 17 1到N编号。当N为0时,输入结束,该用例不被处理。 18 输出: 19 对每个测试用例,在1行里输出最少还需要建设的道路数目。 20 样例输入: 21 4 2 22 1 3 23 4 3 24 3 3 25 1 2 26 1 3 27 2 3 28 5 2 29 1 2 30 3 5 31 999 0 32 0 33 样例输出: 34 1 35 0 36 2 37 998 38 */ 39 40 #include<cstdio> 41 using namespace std; 42 43 #define N 1000 44 45 int Tree[N]; 46 //查找某个节点所在树的根节点 47 int findRoot(int x) 48 { 49 if(Tree[x] == -1) 50 return x; 51 else 52 { 53 int tmp = findRoot(Tree[x]); 54 Tree[x] = tmp; 55 return tmp; 56 } 57 } 58 59 int main() 60 { 61 int n, m; 62 while(scanf_s("%d", &n) != EOF && n != 0) 63 { 64 scanf_s("%d", &m); 65 //初始时,所有节点都是孤立的集合,即其所在集合只有一个节点,其本身就是所在树的根节点 66 for(int i = 1 ; i <= n ; i ++) 67 Tree[i] = -1; 68 69 while(m -- != 0)//读入边信息 70 { 71 int a, b; 72 scanf_s("%d%d", &a, &b); 73 a = findRoot(a); 74 b = findRoot(b);//查找两个顶点所在的集合信息 75 if(a != b) 76 Tree[a] = b;//若两个顶点不在同一个集合,则合并这两个集合 77 } 78 79 int ans = 0; 80 for(int i = 1 ; i <= n ; i ++) 81 { 82 if(Tree[i] == -1) 83 ans ++;//统计所有节点中根节点的个数 84 } 85 86 printf_s("%d ", ans - 1);//ans-1即是所修道路的最小个数 87 } 88 89 return 0; 90 }