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 }