7-25 朋友圈 (25分)--并查集

参考

主要思路:

1.将每个学生视为树的一个结点,用一个数组存储每个结点的前驱结点,当只有一个单独的学生的时候,将前驱设为他本身。然后每行第一个学生a与这一行的其余学生b1、b2……bn分别作合并操作,即a所在的树与bn所在的树相比较,将深度小的那一棵树的根节点x前驱设为深度大的那一棵树的根节点y,这样,两棵树就合在一起了,这样a和bn以及他们之前所在树的所有结点的根结点都变为了y,在判断是不是朋友的时候,只需要判断他们的根节点相不相同即可。

2.深度小的树合并到深度大的树,深度大的树的深度并没有增加。

3.深度相同的两棵树合并,深度为比原来增加1。

 2 #include <iostream>
 3 #include <string>
 4 #include <cstring>
 5 using namespace std;
 6 int r[30001] = {0};//储存每个结点的前驱
 7 int depth[30001] = {0};//储存树的深度,假设一个结点时深度为0
 8 int find(int k)//查找出根节点
 9 {
10     int root = k;
11     while (root != r[root])
12     {
13         root = r[root];
14     }
15     return root;
16 }
17 void merge(int a, int b)
18 {
19     int x = find(a),y=find(b);
20     if(x < y)
21     {
22         r[x] = y;
23     }
24     else if(y < x)
25     {
26         r[y] = x;
27     }
28     else if(x == y && x!=y)
29     {
30         r[x] = y;
31         depth[y]++;
32     }
33 }
34 int main()
35 {
36     int c[30001] = {0};
37     int n1, n2;
38     cin >> n2 >> n1;
39     for(int i=0;i<=n2;i++)r[i]=i;//初始化,把每个单独的结点看成一棵树,所以前驱设为自己
40     for (int i = 0; i < n1; i++)
41     {
42         int n;
43         cin >> n;
44         int f;
45         for (int j = 0; j < n; j++)
46         {
47             int t;
48             cin >> t;
49             if(j==0) f=t;//f储存第一个输入的结点
50             merge(t,f);
51         }
52     }
53     int max_ = 0;
54     for (int i = 1; i <= n2; i++)
55     {
56             int t = ++c[find(i)];
57               if (max_ < t)
58             max_ = t;
59     }
60     cout << max_ << endl;
61     return 0;
62 }
原文地址:https://www.cnblogs.com/2020R/p/12452589.html