0
点赞
收藏
分享

微信扫一扫

NOI银河英雄传说(并查集)

皮皮球场 2022-04-08 阅读 73

问题:

解决:

思路上比较简单,利用并查集

1.合并操作,直接将两个元素所在的树合并,并且将新的树里每个元素到根节点的距离更新

2.查询操作,有两种情况

a.两元素不在同一棵树里,说明距离无法计算,输出-1

b.两元素在同一棵树里,利用两元素到根节点的距离作差来计算,具体的话又分成两种情况,两元素相邻或者不相邻,加个特判就可以

具体细节看代码

注意:

这道题多少有点无奈

首先大数据读入,必须用 scanf 和 printf ,其次是测试数据,它的数据间隔有一些中间是两个空格的,读入这个字符最好用 %s ,要不就 空格+%c ,因为这个我WA了好几次

代码:

#include <bits/stdc++.h>
using namespace std;
#define N 30010
//cnt_size[i]表示i所在链上的元素个数
//res_dis[i]表示i到其跟节点的距离
int f[N], res_dis[N], cnt_size[N];
int find(int x){
    if(f[x] != x){
        int fx = find(f[x]);
        //路径压缩
        res_dis[x] += res_dis[f[x]];  //修改x到根节点的距离
        f[x] = fx;  //修改根节点
    }
    return f[x];
}
int main(void)
{
    int t; scanf("%d", &t);
    for(int i = 1; i < N; i++){
            //独立元素size为1
            cnt_size[i] = 1;
            f[i] = i;
        }
    while(t--){
        char c; int a, b;
        scanf(" %c%d%d", &c,&a,&b);
        int pa = find(a), pb = find(b);
        if(c == 'M'){
            //pa到根节点距离等于pb链中元素个数
            res_dis[pa] = cnt_size[pb];
            //更新pb链大小
            cnt_size[pb] += cnt_size[pa];
            f[pa] = pb;  //根节点修改
        }
        else{
            if(pa != pb) printf("-1\n");
            else  printf("%d\n", max(0, abs(res_dis[a] - res_dis[b]) - 1));
        }
    }    
    return 0;    
}
举报

相关推荐

0 条评论