P1536. 村村通

考点

  • 并查集

题解

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
#include <bits/stdc++.h>
using namespace std;
const int LEN = 1050;
int ans, fa[LEN];

int find(int fa[], int x)
{
if (x == fa[x])
return x;
return fa[x] = find(fa, fa[x]);
}

void join(int fa[], int a, int b)
{
int f1 = find(fa, a), f2 = find(fa, b);
if (f1 != f2)
{
//每次合并都会减少一个连通块
fa[f1] = f2;
--ans;
}
}

int main()
{
int n, m, a, b;
while (cin >> n && n)
{
for (int i = 1; i <= n; ++i)
fa[i] = i;
ans = n;
cin >> m;
while (m--)
{
cin >> a >> b;
join(fa, a, b);
}
cout << ans - 1 << endl;
}
return 0;
}

思路

根据题眼任何两个城镇间都可以实现交通,也就是将所有城镇并入到同一个集合中,考虑并查集

先处理每条存在的边,即把每条存在的边所连接的两个结点用并查集合并起来

然后通过记录不同的代表元个数,就可以知道有多少个集合,即有多少个连通块了

每次合并连通块的个数都会减一,若要满足题意,则连通块应该只有一个;所以答案就是连通块数 - 1