问题描述
w星球的一个种植园,被分成 m * n 个小格子(东西方向m行,南北方向n列)。每个格子里种了一株合根植物。
这种植物有个特点,它的根可能会沿着南北或东西方向伸展,从而与另一个格子的植物合成为一体。
如果我们告诉你哪些小格子间出现了连根现象,你能说出这个园中一共有多少株合根植物吗?
输入格式
第一行,两个整数m,n,用空格分开,表示格子的行数、列数(1<m,n<1000)。
接下来一行,一个整数k,表示下面还有k行数据(0<k<100000)
接下来k行,第行两个整数a,b,表示编号为a的小格子和编号为b的小格子合根了。
格子的编号一行一行,从上到下,从左到右编号。
比如:5 * 4 的小格子,编号:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
17 18 19 20
样例输入
5 4
16
2 3
1 5
5 9
4 8
7 8
9 10
10 11
11 12
10 14
12 16
14 18
17 18
15 19
19 20
9 13
13 17
样例输出
5
样例说明
其合根情况参考下图
借鉴: java 历届试题 合根植物
思路:
1. 创建一个数组,其值等于下标值,即 n[i]=i ;
2. 输入编号a,b ;
3. 若n[a]=a, n[b]=b, 则 n[a]=b ;
若 n[a]!=a (或n[b]!=b),则 通过 递归 找到 n[i]=i ,并将其全部赋值为 i 。将 n[i] = n[b],此时,b 成为新的根点,即 n[b]=b。
private static void u(int a, int b) {
if(f(a)==f(b))
return;
n[f(a)]=f(b); //n[a]!=a时,属于a集合中的值变成相同,且根值=f(b),即集合a的根值变为f(b)。此时,若n[b]=b,则b为集合a的根值。若n[b]!=b,则a,b集合合并,原集合b的根值成为新的根值。
}
private static int f(int i)
{
if(n[i]==i)
return i;
return n[i]=f(n[i]); //递归,将属于集合i中的值变成相同。return : 将n[i]=i的i值(即集合i的根值)返回。
}
4. 输入完成之后,创建Set对象 ,遍历数组,set.add(),调用之前的递归函数,使得同一集合中的数值相等。
Set<Integer> set=new HashSet<Integer>();
for(int i=0;i<m*n;i++)
{
set.add(f(i));
}
5. 输出set中元素的个数。
System.out.println(set.size());
6. 可以通过如下方法,查看set中的元素数值。
for(Integer value : set){
System.out.print(value+" ");
}
整体代码
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Main {
static int[] n ;
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int j = cin.nextInt();
int k = cin.nextInt();
int s = cin.nextInt();
n = new int[j*k];
for(int i=0;i<j*k;i++) {
n[i]=i;
}
int a,b;
for(int i=0;i<s;i++) {
a = cin.nextInt()-1;
b = cin.nextInt()-1;
su(a,b);
}
Set<Integer> set = new HashSet<Integer>();
for(int i=0;i<j*k;i++) {
set.add(f(i));
}
System.out.println(set.size());
cin.close();
}
static void su(int a,int b) {
if(f(a)==f(b))
return;
else {
n[f(a)]=f(b);
}
}
static int f(int a) {
if(n[a]==a)
return a;
return n[a] = f(n[a]);
}
}
遇到的问题及相关文章
https://blog.csdn.net/qq_43419016/article/details/98482061
并查集
合根植物