描述
给定一个无向图和其中的所有边,判断这个图是否所有顶点都是连通的。
输入描述:
每组数据的第一行是两个整数 n 和 m(0<=n<=1000)。n 表示图的顶点数目,m 表示图中边的数目。随后有 m 行数据,每行有两个值 x 和 y(0<x, y <=n),表示顶点 x 和 y 相连,顶点的编号从 1 开始计算。输入不保证这些边是否重复。
输出描述:
对于每组输入数据,如果所有顶点都是连通的,输出"YES",否则输出"NO"。
示例1
输入:
4 3 1 2 2 3 3 2 3 2 1 2 2 3 0 0
输出:
NO YES
代码如下
import java.util.Scanner;
/*
* 连通图
*/
public class ConnectionPhoto {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
OuterLoop:
while (scanner.hasNext()) {
//n表示图的顶点数
int n = scanner.nextInt();
//m表示边的数目
int m = scanner.nextInt();
if (m == 0||n == 0) {
break;
}
UnionFind uf = new UnionFind(n);
for (int i = 0; i < m; i++) {
//连接边的两个顶点
int x = scanner.nextInt();
int y = scanner.nextInt();
uf.Union(x, y);
}
//找到第一个节点的父亲结点
int root = uf.find(1);
for (int i = 1; i <= n; i++) {
if (uf.find(i) == root) {
//如果所有结点的根结点都相同,则说明所有元素在一个集合中
continue;
}else {
//只要有一个结点的根结点与第一个节点不同,则说明有元素和其他元素不在同一个集合中
System.out.println("NO");
//跳出最外层循环
continue OuterLoop;
}
}
System.out.println("YES");
}
}
}
class UnionFind{
int[] height;
int[] parent;
public UnionFind(int n) {
height = new int[n+1];
parent = new int[n+1];
for (int i = 1; i < n+1; i++) {
height[i] = 0;
parent[i] = i;
}
}
//查操作
public int find(int i) { //找到根结点
if (parent[i] != i) {
parent[i] = find(parent[i]);
}
return parent[i];
}
//合并操作
public void Union(int x,int y){
int rootX = find(x);
int rootY = find(y);
if (rootX == rootY) {
return;
}
if (height[rootX] > height[rootY]) {
parent[rootY] = rootX;
}else if (height[rootX] < height[rootY]) {
parent[rootX] = rootY;
}else {
parent[rootY] = rootX;
height[rootX]++;
}
}
}