判断连通性除了可以用学习过的 BFS、DFS 外,还可以用一个叫”并查集“的算法
并查集又可以理解为不相交集合上的合并查询
并查集是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并和查询问题。经典的应用有:判断连通性、最小生成树 Kruskal 算法、最近公共祖先(Least Common Ancestors, LCA)等。并查集在算法竞赛中也十分常见:一是简单且高效,二是应用很直观,三是容易和其他数据结构和算法结合。
第一题 剪邮票
如果用BFS做
import java.util.*;
public class Main {
private static int[] map = {1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 14};
private static int count = 0;
public static void main(String[] args) {
//Scanner s = new Scanner(System.in);
prem(0, 11);
System.out.println(count/120);
}
private static void prem(int s, int t) {//求12个数取5个的全排列
if (s == 5) {
fun1();
for (int i = 0; i < 5; i++) {
System.out.print(map[i] + " ");
}
System.out.println();
return;
}
for (int i = s; i <= t; i++) {
swap(s, i);
prem(s + 1, t);
swap(s, i);
}
}
private static void fun1() {
int[] visited = {1, 0, 0, 0, 0};
int temp = 1;
Queue<Integer> queue = new LinkedList<>();
queue.add(map[0]);
while (!queue.isEmpty()) {
int x = queue.poll();
//System.out.println(x);
for (int i = 1; i <= 4; i++) {
if ((map[i] - 1 == x && visited[i] == 0) || (map[i] + 5 == x && visited[i] == 0) || (map[i] - 5 == x && visited[i] == 0) || (map[i] + 1 == x && visited[i] == 0)) {
visited[i] = 1;
queue.add(map[i]);
temp++;
}
}
}
if (temp == 5) {
count++;
}
}
private static void swap(int s, int t) {
int temp;
temp = map[s];
map[s] = map[t];
map[t] = temp;
}
}
因为全排列前面有重复的情况,所以最后的结果要除(5*4*3*2*1)
感觉bfs比并查集简单
第二题 蓝桥幼儿园
样例输入
5 5
2 1 2
1 1 3
2 1 3
1 2 3
2 1
样例输出
NO
YES
YES
import java.util.*;
public class Main {
private static int[] map;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int N = scan.nextInt();
int M = scan.nextInt();
map = new int[N+1];
for (int i = 1; i <= N; i++) {
map[i] = i;
}
for (int i = 1; i <= M; i++) {
int op = scan.nextInt();
int x = scan.nextInt();
int y = scan.nextInt();
if(op == 1) {
merge_set(x,y);
}
if(op == 2) {
if(find_set(x) == find_set(y)) {
System.out.println("Yes");
}else {
System.out.println("No");
}
}
}
scan.close();
}
private static void merge_set(int x,int y) {
x = find_set(x);
y = find_set(y);
if(x!=y) {
map[x] = map[y];
}
}
private static int find_set(int k) {
if(k != map[k]) {
map[k] = find_set(map[k]);
}
return map[k];
}
}
过不了全部的数据,不知道为什么,头秃了。
第三题 合根植物
样例输入
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
import java.util.*;
public class Main {
private static int[] map;
private static int m;
private static int n;
private static int count = 0;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
m = scan.nextInt();
n = scan.nextInt();
map = new int[m*n+1];
init();
int k = scan.nextInt();
for(int i = 1;i<=k;i++) {
int x = scan.nextInt();
int y = scan.nextInt();
merge_set(x, y);
}
for(int i = 1;i<=n*m;i++) {
if(map[i] == i) {
count++;
}
}
System.out.println(count);
}
private static void init() {
for(int i =1;i<=m*n;i++) {
map[i] = i;
}
}
private static int find_set(int k) {
if(k!=map[k]) {
map[k] = find_set(map[k]);
return map[k];
}
return k;
}
private static void merge_set(int x,int y) {
if(find_set(x)!=find_set(y)) {
map[find_set(x)] = find_set(y);
}
}
}
第四题 修改数组
样例输入
5
2 1 1 3 4
样例输出
2 1 3 4 5