描述
给定一个无向图和其中的所有边,判断这个图是否所有顶点都是连通的。
输入描述:
每组数据的第一行是两个整数 n 和 m(0<=n<=1000)。n 表示图的顶点数目,m 表示图中边的数目。随后有 m 行数据,每行有两个值 x 和 y(0<x, y <=n),表示顶点 x 和 y 相连,顶点的编号从 1 开始计算。输入不保证这些边是否重复。
输出描述:
对于每组输入数据,如果所有顶点都是连通的,输出"YES",否则输出"NO"。
输入
4 3
1 2
2 3
3 2
3 2
1 2
2 3
0 0
输出
NO
YES
代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <vector>
using namespace std;
int father[1010];
// i 数组下标是集合数据编号 father[i] 集合数据的父亲的编号
// 根i father[i] 和 i 相同
void InitDisjointSet(int n) {
// 0~n-1
for (int i = 0; i < n; ++i) {
father[i] = i;
}
}
int FindDisjointSet(int u) {
if (u == father[u]) {
return u;
}
else {
father[u] = FindDisjointSet(father[u]);
return father[u];
}
}
int setCount;
void UnionDisjointSet(int u, int v) {
int uroot = FindDisjointSet(u);
int vroot = FindDisjointSet(v);
if (uroot != vroot) {
--setCount;
}
father[vroot] = uroot;
}
int main() {
int n, m;
while (scanf("%d%d", &n, &m) != EOF) {
if (n == 0) {
break;
}
InitDisjointSet(n + 1); // 1~n
setCount = n;
for (int i = 0; i < m; ++i) {
int u, v;
scanf("%d%d", &u, &v);
UnionDisjointSet(u, v);
}
printf("%d\n", setCount - 1);
}
}