AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

P1196 银河英雄传说

作者: 作者的头像   cccccccup ,  2025-07-06 17:57:06 · 福建 ,  所有人可见 ,  阅读 5


0


题目

微信截图_20250706170615.png
微信截图_20250706170633.png

分析

很明显是需要维护信息的并查集

易错点

合并时候

习惯性地判断是否fx和fy相等,如果相等就不用再合并了

合并时注意方向

微信截图_20250706170852.png
f[fx]=fy;

对d[fy]的赋值

不是赋值为1,而是要看fy的集合一共有多少元素,因为在此基础上,添加到末尾的
因此还要维护一个sum数组,根节点的下标对应的值为根节点所在集合的元素总数

d[]不能复制为1!!!!

因为如果d赋值为1
那么第二层节点在find时依旧会递归1次,那么d数组就会累加
d数组累加的次数和find的调用次数有关,因此两个点之间节点的数量就错了
因此d数组要初始化为0

最后小细节

两个节点中间的节点数是abs(d[x]-d[y])-1!!!记得减1

#include <bits/stdc++.h>
using namespace std;

const int N=30007;
int t;
int f[N],d[N];
int sum[N];

int find(int x)
{
    if(f[x]==x) return f[x];
    int t=find(f[x]);
    d[x]=d[x]+d[f[x]];
    f[x]=t;
    return f[x];
}

int main()
{
    //要维护信息了
    //感觉第几列只是个幌子? 
     scanf("%d",&t);
     for(int i=1;i<=30001;i++){
        f[i]=i;
        d[i]=0;
        sum[i]=1;
     } 
     for(int i=1;i<=t;i++){
        char op[2];int x,y;
        scanf("%s%d%d",op,&x,&y);
        if(op[0]=='M'){
            //第x号战舰所在的整个战舰队列,整体接到第y号战舰的尾部
            int fx=find(x);int fy=find(y);
            if(fx==fy) continue;
            f[fx]=fy;
            d[fx]=sum[fy];
            sum[fy]+=sum[fx];
        }else{
            int fx=find(x);
            int fy=find(y);
            if(fx!=fy) printf("-1\n");
            else  printf("%d\n",abs(d[x]-d[y])-1);
        }
    }

    return 0;
}

0 评论

App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息