并查集

Myth丶恋晨 2022-06-08 09:24 367阅读 0赞

题目
某学校近期要组织全校同学出去参加某项活动,由于人数众多,学校决定让同学们自行组队,以小组为单位进行活动。假设学校一共n个同学,每个同学有一个唯一的数字作为标签,标签数字范围1到n。为了统计分组情况,学校要求有分组意愿的同学提交一个数字,表示其会和以该数字为标签的同学分到一组。
现在告诉你每位同学的选择,你能统计出一共有多少个小组么?
注意如果1和2一组,2和3一组,那么1,2,3属于一组。默认自己一定和自己在一组。
输入
输入包括两行,第一行是同学的个数n
第二行一共有n个数,分别代表第i个同学愿意和哪个同学组队
输出
输出包括一个整数,表示组的队数

这是一道经典的并查集算法,以下为代码

  1. import java.util.Scanner;
  2. public class Main {
  3. static int[] pre ;
  4. static int[] t;
  5. static int count;
  6. public static void main(String[] args) {
  7. Scanner in = new Scanner(System.in);
  8. int n = in.nextInt();
  9. int[] array = new int[n];
  10. pre = new int[n+1];//记录前导点
  11. for (int i = 1; i <= n; i++) {
  12. //初始化前导点
  13. pre[i] = i;
  14. }
  15. for (int i = 0; i < n; i++) {
  16. array[i] = in.nextInt();
  17. union(i+1, array[i]);
  18. }
  19. t = new int[n+1];//记录根节点
  20. for (int i = 1; i <= n; i++) {
  21. t[pre[i]] = 1;
  22. }
  23. for (int i = 0; i < n; i++) {
  24. if(t[i] == 1)
  25. count++;
  26. }
  27. System.out.println(count);
  28. }
  29. /**
  30. * 查找根节点
  31. * @param x
  32. * @return
  33. */
  34. private static int find(int x){
  35. int r = x;
  36. while(pre[r]!=r){
  37. r = pre[r];
  38. }
  39. int i = x,j;
  40. while(i!=r){
  41. //更新前驱节点为根节点
  42. j = pre[i];
  43. pre[i] = r;
  44. i = j;
  45. }
  46. return r;
  47. }
  48. private static void union(int x, int y){
  49. int fx = find(x);
  50. int fy = find(y);
  51. if(fx!=fy)//如果根节点不同则合并
  52. pre[fx] = fy;
  53. }
  54. }

并查集通常还会用来判断是否有环,例如下题

题目:在一个王国里,建立很多瞭望塔,瞭望塔之间连接有围墙。给出瞭望塔个数n,各个塔之间的围墙数m。接着给出m组A B;
表示A B之间有围墙连接,问这些哨塔,围墙把土地分割成了几个部分。

土地被分割成几部分其实就是指有多少个环,对于并查集查找函数,如果两个节点的父节点不相同,则合并这两个节点所在集合,否则说明这两个节点之间原本就存在通路,再加上这条边就组成了环。
代码如下:

  1. import java.util.Scanner;
  2. public class Main {
  3. static int[] pre ;
  4. static int count;
  5. public static void main(String[] args) {
  6. Scanner in = new Scanner(System.in);
  7. int n = in.nextInt();
  8. int m = in.nextInt();
  9. int[] array = new int[n];
  10. pre = new int[n+1];//记录前导点
  11. for (int i = 1; i <= n; i++) {
  12. //初始化前导点
  13. pre[i] = i;
  14. }
  15. for (int i = 0; i < m; i++) {
  16. int a = in.nextInt();
  17. int b = in.nextInt();
  18. union(a, b);
  19. }
  20. System.out.println(count);
  21. }
  22. /**
  23. * 查找根节点
  24. * @param x
  25. * @return
  26. */
  27. private static int find(int x){
  28. int r = x;
  29. while(pre[r]!=r){
  30. r = pre[r];
  31. }
  32. return r;
  33. }
  34. private static void union(int x, int y){
  35. int fx = find(x);
  36. int fy = find(y);
  37. if(fx!=fy)//如果根节点不同则合并
  38. pre[fx] = fy;
  39. else
  40. count++;
  41. }
  42. }

发表评论

表情:
评论列表 (有 0 条评论,367人围观)

还没有评论,来说两句吧...

相关阅读

    相关

    并查集JAVA版框架 并查集是一种用来管理元素分组情况的数据结构。 并查集可以高效地进行如下操作: \--查询元素a和元素b是否属于同一组

    相关

    这个文章是几年前水acm的时候转的, 当时也不知道作者是谁, 要是有人知道的话说一下吧 并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了。以前我无法解决的

    相关

    > 题目 > 某学校近期要组织全校同学出去参加某项活动,由于人数众多,学校决定让同学们自行组队,以小组为单位进行活动。假设学校一共n个同学,每个同学有一个唯一的数字作为标签

    相关

    森林: 森林是由若干棵互不相交的树组成,两棵树分别独立,没有交集 ![20181112082744488.png][] 并查集: 并查集的结构和森林十分相似,是

    相关

    来看一个实例,[杭电1232畅通工程][1232] 首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的。最后要解决的是整幅图的连通性

    相关

    > 并查集是一种树形的数据结构,用于集合的合并。 与C++STL相比的优势: 1. 可以同时维护多个集合 2. 快速的合并两个集合 \\现实: 用数组实现。fat

    相关

    例题: ![输入样例][20190805122001677.png] 输入样例,第一行为一个整数n,代表有n台电脑,编号1-n;接下来进行一系列操作,当输入‘c’时,判

    相关

    一、算法解释 用于解决一些有N个元素的集合应用问题。 1、将每个元素初始化为自身单独成为一个集合。用p\[i\]的值表示该元素所在集合。 ![这里写图片描述][S

    相关

    并查集的作用就是快速判断两个元素是否在同一个集合中,快速将两个集合合并 基本模板 include <iostream> include <a