统计图中的连通分量的个数,如果连通分量个数等于1,说明图中只存在一个连通分量,图为连通图;如果连通分量个数大于1,说明图中存在多个连通分量,图不为连通图。
判断有多少个连通分量就是判断有多少个根。
public class UnionFindYingYong {
static int[] parent;
static int[] size;
public static void main(String[] args) {
int n = 5;
parent = new int[n];
size = new int[n];
for(int i = 0; i < n; i++){
parent[i] = i;
size[i] = 1;
}
//将图中的0和1连通起来,2和4连通起来,3自己是一个
union(0, 1);
union(2, 4);
int cnt = 0;//记录连通分量个数
for(int i = 0; i < n; i++){
//if(find(i) == i){//每个集合只能有一个根,根的根节点还是它自己
if(parent[i] == i){//根节点的parent[i] == i
cnt++;
}
}
System.out.println(cnt);
}
public static int find(int x){
while(x != parent[x]){
//parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
public static void union(int p, int q){
int rootP = find(p);
int rootQ = find(q);
if(rootP == rootQ){
return;
}
if(size[rootP] > size[rootQ]){
parent[rootQ] = rootP;
size[rootP] += size[rootQ];
}else{
parent[rootP] = rootQ;
size[rootQ] += size[rootP];
}
}
public static boolean connected(int p, int q){
return find(p) == find(q);
}
}
判断是否成环:
先连接0、1,再连接1、2,此时如果再连接0、2,因为0和2已经属于同一个集合(因为它们有共同的根节点),即0和2在没有0-2这条边的时候就已经连通了,如果再加上这条边的话那从0到2就有两条路径可达,就说明存在一个环了。
public class UnionFindYingYong02 {
static int[] parent;
static int[] size;
public static void main(String[] args) {
int n = 5;
parent = new int[n];
size = new int[n];
for(int i = 0; i < n; i++){
parent[i] = i;
size[i] = 1;
}
//初始化图,将以下点连接起来
int[][] edge = {{0, 1}, {1, 2}, {0, 2}, {2, 3}};
for(int i = 0; i < edge.length; i++){
int p = edge[i][0];
int q = edge[i][1];
if(find(p) == find(q)){
System.out.println("成环!");
return;
}
union(p, q);
}
}
public static int find(int x){
while(parent[x] != x){
x = parent[x];
}
return x;
}
public static void union(int p, int q){
int rootP = find(p);
int rootQ = find(q);
if(rootP == rootQ){
//其实可以在这打个标记,如果程序执行到这里了,说明有环
return;
}
if(size[rootP] > size[rootQ]){
parent[rootQ] = rootP;
size[rootP] += size[rootQ];
}else{
parent[rootP] = rootQ;
size[rootQ] += size[rootP];
}
}
}
other version:
public class UnionFindYingYong02 {
static int[] parent;
static int[] size;
public static void main(String[] args) {
int n = 5;
parent = new int[n];
size = new int[n];
for(int i = 0; i < n; i++){
parent[i] = i;
size[i] = 1;
}
//初始化图,将以下点连接起来
int[][] edge = {{0, 1}, {1, 2}, {0, 2}, {2, 3}};
for(int i = 0; i < edge.length; i++){
int p = edge[i][0];
int q = edge[i][1];
if(union(p, q) == 0){
System.out.println("成环!");
return;
}
}
}
public static int find(int x){
while(parent[x] != x){
x = parent[x];
}
return x;
}
public static int union(int p, int q){
int rootP = find(p);
int rootQ = find(q);
if(rootP == rootQ){
return 0;
}
if(size[rootP] > size[rootQ]){
parent[rootQ] = rootP;
size[rootP] += size[rootQ];
}else{
parent[rootP] = rootQ;
size[rootQ] += size[rootP];
}
return 1;
}
}