一、题目描述
二、代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
@SuppressWarnings("resource")
Scanner in = new Scanner(System.in);
int m = in.nextInt();
int n = in.nextInt();
int k = in.nextInt();
int repeat_num = 0;
int res = 0;
int all = m * n ;
int[] book = new int[all + 1];
for(int i = 0; i < k; i++){
int a = in.nextInt();
int b = in.nextInt();
if(book[a] == 0 && book[b] == 0){
book[a] = book[b] = ++res;
}
else if(book[a] != 0 && book[b] == 0){
book[b] = book[a];
}
else if (book[b] != 0 && book[a] == 0) {
book[a] = book[b];
}
else if (book[a] != 0 && book[b] != 0 && book[a] != book[b]) {
int tmp = book[b];
for(int j = 1; j <= all; j++){
if(book[j] == tmp){
book[j] = book[a];
}
}
repeat_num ++;
}
}
res = res - repeat_num;
for(int i = 1; i <= m * n; i++){
if(book[i] == 0)
res++;
}
System.out.println(res);
}
}
三、思路记录
- 读入不谈。解题思路来源于 Floodfill 。
- 使用一个数组(此处是book[ ])记录 种植园格子里的植物是否连根。
- 个人觉得这道题表述不合理,最终计算的并非是“合根植物的数量”,而是“植物的数量”。导致解题最终需要再遍历一遍数组,找出“没有连根情况发生的植物”。
- 每次读入两株植物(设为a、b):
- 1)如果都没有,即把它们都标记为连根植物,book[a] = book[b];
- 2)如果一株植物已经被标记过(假设为a)、一株植物未被标记过(假设为b),那么 book[b] = book[a];
- 3)如果两株植物都被标记过,注意会有两种情况:3.1)这两株植物已经在 book 数组中被标记为同一株连根植物,那么不处理即可 ;3.2)这两株植物在目前的 book 数组中是不同株连根植物,现要把它们标记为同一株连根植物,那么就需要将其中的一株植物标记为另一株植物,之后在记录植物数量的变量中(此处为res)减去 1,即原来我们以为是两株植物、结果现在才发现是同一株、那么总数要减一。
- 4)此处给出样例输入输出运算结束的 book 数组。
四、结果
日常不会改进算法...下载了数据,运算结果是正确的。
五、改进
博主已被自己蠢死...
并查集并查集并查集....
参考资料:
并查集简略易懂介绍:https://blog.csdn.net/liujian20150808/article/details/50848646
本题参考:https://blog.csdn.net/qq_34525938/article/details/79334313
5.1 代码
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Main {
static int[] book;
public static void main(String[] args) {
@SuppressWarnings("resource")
Scanner in = new Scanner(System.in);
int m = in.nextInt();
int n = in.nextInt();
int k = in.nextInt();
int all = m * n ;
book = new int[all];
for(int i = 0; i < all; i++){
book[i] = i;
}
int a, b;
for(int i = 0; i < k; i++){
a = in.nextInt() - 1;
b = in.nextInt() - 1;
union(a, b);
}
Set<Integer> set = new HashSet<Integer>();
for(int i = 0; i < all; i++){
set.add(find(i));
}
System.out.println(set.size());
}
private static void union(int a, int b) {
int find_res_a, find_res_b;
find_res_a = find(a);
find_res_b = find(b);
//随意指定一项作为源头
if(find_res_a != find_res_b)
book[find_res_a] = find_res_b;
}
private static int find(int x) {
//寻找 x 的源头
int r = x;
while(book[r] != r)
r = book[r];
return r;
}
}