1 #include <cstdio>
2 #include <cstdlib>
3 #include <iostream>
4 #include <algorithm>
5 #include <cstring>
6 using namespace std;
7
8 #define MAXN 5000
9 int fa[MAXN]; //父节点
10 int Rank[MAXN]; //数的高度
11 int ans;
12
13 void init(int n) //初始化
14 {
15 for (int i = 0; i < n; i++)
16 {
17 fa[i] = i; //每个人的根都是自己
18 Rank[i] = 0; //每颗树的高度都为0
19 }
20 }
21
22 int find(int x) //查(查询根节点)
23 {
24 if(fa[x] == x)
25 return x;
26 else
27 {
28 fa[x] = find(fa[x]); //递归求根节点
29 return fa[x];
30 }
31 }
32
33 void set_union(int x, int y) //(并)
34 {
35 x = find(x);
36 y = find(y);
37 if (x == y)
38 return;
39 if (Rank[x] < Rank[y])
40 fa[x] = y;
41 else
42 fa[y] = x;
43 if (Rank[x] == Rank[y])
44 Rank[x]++; //树的高度加一
45 }
46
47 bool same(int x, int y) //判断两个节点是否属于同一个集合
48 {
49 return find(x)==find(y);
50 }
51
52 int main()
53 {
54 int n, m, t;
55 scanf("%d", &t);
56 while (t--)
57 {
58 scanf("%d %d", &n, &m);
59 memset(fa, 0, sizeof(fa));//对父节点进行清零
60 ans = n; //最开始的时候ans = 人数
61 init(n);
62 for (int i = 0; i < m; i++)
63 {
64 int x, y;
65 scanf("%d %d", &x, &y);
66 if (same(x, y))
67 continue;
68 else
69 {
70 set_union(x, y);
71 ans--;
72 }
73 }
74 printf("%d
", ans);
75 }
76 77 return 0;
78 }