238. 银河英雄传说 AcWing

原题链接

考察: 并查集

通过这道题算是把食物链没搞懂的问题又弄明白了点

很明显根据题意我们需要维护一个距离数组,表示父节点到子节点的距离.

       当操作是C的时候,我们实际上在进行C操作之前是进行过路径压缩的,因此d[x]的距离变成了x到根节点的距离,d[y]的距离就算y到根节点的距离,因此两者的距离差就是:

          abs(d[x]-d[y])-1

       当操作是M的时候,我们在M操作里实际上也进行了路径压缩,但压缩的不是x到父节点的距离,而是父节点到新根节点的距离.题目要求我们将x接到y的尾部,实际上M操作里我们为了配合并查集的Merge操作,是将x结点接到了y的根节点处,而d[px]的距离也被压缩成px到根节点的距离,也就是y集合的大小

       那么x结点的距离如何更新?当我们用到x的距离的时候自然就会更新,也就是在find函数里对x距离进行路径压缩

 1 #include <iostream>
 2 #include <cmath>
 3 using namespace std;
 4 const int N = 30010;
 5 int p[N],d[N],sz[N];
 6 int find(int x)
 7 {
 8     if(p[x]!=x){
 9         int t = find(p[x]);//这里是将x与父节点的距离压缩成x与根节点的距离
10         d[x]+=d[p[x]];
11         p[x] = t;
12     }
13     return p[x];
14 }
15 int main()
16 {
17     int t;
18     char op[2];
19     scanf("%d",&t);
20     for(int i=1;i<=N-10;i++) { p[i] = i; sz[i] = 1; }
21     while(t--){
22         int x,y;
23         scanf("%s%d%d",op,&x,&y); 
24         int px = find(x); int py = find(y);
25         if(op[0]=='M'){
26             d[px] = sz[py];//这里实际上也是路径压缩,但是将x的父节点的路径压缩,x与父节点的距离不变
27             sz[py]+=sz[px];//在题意理解上px是跟在y所在列的后面,但实际上合并是跟在y根节点的后面
28             p[px] = py;
29         }else if(op[0]=='C'){
30             if(px!=py) printf("-1\n");
31             else printf("%d\n",abs(d[x]-d[y])-1);
32         }
33     }
34     return 0;
35 }

 

posted @ 2021-01-03 14:39  acmloser  阅读(91)  评论(0编辑  收藏  举报