连接电脑

1.3k 词

题目描述

机房里有若干台电脑,其中有一些电脑已经相互连接。如果A和B通过网线相连,并且B与C也通过网线相连,那么即便A和C之间没有直接的网线相连,也可以认为A和C是相连的。由于机房里的布线比较乱,并不是所有电脑都相互连通,请问在不变动当前布线情况下,最少要购买几条网线才能使得机房所有电脑都两两连通。 

输入

多组数据。每组数据第一行为整数N,M。N是电脑数量,M是机房已布置好的网线数量。接下来M行,每行为整数A,B。表明A,B之间通过一条网线直接相连。这里可以认为网线是不分方向的,即A->B等价于B->A。
(0 < N <= 200,0 <= M <= 10000,0 <= A,B <= N 。) N=0和M=0为输入结束,不需要处理。 

输出

每组一个整数,即最少还要购买几根网线。

样例输入

1
2
3
4
5
6
4 2
1 2
2 3
4 0
1 0
0 0

样例输出

1
2
3
1
3
0

提示

n个电脑编号为1~n

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <algorithm>
using namespace std;
#define endl '\n'
const int maxn = 200 + 10;
int F[maxn];
void init(int n) {
for (int i = 1; i <= n; i++) {
F[i] = i;
}
}
bool is_root(int x) {
return F[x] == x;
}
int find(int x) {
if (is_root(x))return x;
return F[x] = find(F[x]);
}
bool merge(int x, int y) {
int fx = find(x), fy = find(y);
if (fx == fy)return false;
F[fx] = fy;
return true;
}

int count(int n) {
int cnt = 0;
for (int i = 1; i <= n; i++)
if (F[i] == i)++cnt;
return cnt;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n, m;
while (cin >> n >> m) {
if (n == 0 && m == 0)break;
init(n);
while (m--) {
int x, y;
cin >> x >> y;
merge(x, y);
}
cout << count(n) - 1 << endl;
}
return 0;
}