并查集思想
关于并查集的思想,如果不了解的话可以参考一下这篇文章:链接: 【算法与数据结构】—— 并查集.
简单来说,我们想如果要知道数据间是否是连通的,或者是否具有某种关系,就可以通过find()函数来查找它们是否拥有公共的上级,同时,我们还可以通过join()函数来添加上级。
find()函数
find()函数的功能是为了找到它的最上级。这里我们直接使用优化的并查集,我们先定义一个数组pre[],pre[i]存放的就是i的最上级。具体实现代码:
public static int find(int x) {
if(pre[x] == x) return x;
return pre[x] = find(pre[x]);
}
join()函数
join()函数是起到合并的功能,也就是将它们的最上级指定为同一个(选取哪一个上级随意)
实现代码:
public static void join(int x,int y) {
int fx = find(x),fy = find(y);
if(fx!=fy)
pre[fx] = fy;
}
注意这里是最上级之间的层级设置,不是x,y间的,这个地方没注意我改了半天orz
合根植物
链接: 合根植物.
这里可以看出是很基础的并查集考察了,直接套用模板就好了
完整代码
代码1:
这里的步骤比较清晰,boolean[]相当于辅助数组,方便理解
import java.util.Scanner;
public class test {
public static int[] pre;
public static boolean[] plants;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
int k =sc.nextInt();
pre = new int[m*n+1];
plants = new boolean[m*n+1];
for(int i=1;i<=m*n;i++) {
pre[i] =i;
}
for(int i=0;i<k;i++) {
int x=sc.nextInt();
int y=sc.nextInt();
join(x,y);
}
int count=0;
for(int i=1;i<=m*n;i++) {
plants[find(i)] = true;
}
for(int i=1;i<=m*n;i++) {
if(plants[i])
count++;
}
System.out.println(count);
}
public static int find(int x) {
if(pre[x] != x) return pre[x] = find(pre[x]);
return x;
}
public static void join(int x,int y) {
int fx=find(x),fy = find(y);
if(fx!=fy) {
pre[fy] = fx;
}
}
}
代码2:
这里去掉了boolean[]数组,可以少遍历一次
package test;
import java.util.Scanner;
public class test {
public static int[] pre;
public static int count;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
int k =sc.nextInt();
count = m*n;
pre = new int[m*n+1];
for(int i=1;i<=m*n;i++) {
pre[i] =i;
}
for(int i=0;i<k;i++) {
int x=sc.nextInt();
int y=sc.nextInt();
join(x,y);
}
System.out.println(count);
}
public static int find(int x) {
if(pre[x] != x) return pre[x] = find(pre[x]);
return x;
}
public static void join(int x,int y) {
int fx=find(x),fy = find(y);
if(fx!=fy) {
pre[fy] = fx;
count--;
}
}
}