P1196 [NOI2002] 银河英雄传说

P1196 [NOI2002] 银河英雄传说

题目简述

  1. M i jij 是两个整数(1i,j30000),将 ij 合并

  2. C i jij 是两个整数(1i,j30000),询问 ij 是否在同一列,若是输出 ij 之间距离,不是则输出 1


思路

非常经典的一道并查集题目,很好地加深对并查集的理解,因为正常操作下并查集的 fa[i] 都只是存了祖先,而中间的路径都被压缩了,所以在这题可以通过递归实现对祖先距离的不断更新依次来达到对中间的一个记录过程

具体思路


代码

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
int fa[N],dis[N],num[N];//num[i]以i为开头的队列长度,dis[i]i距离i所在队列开头的长度
int get_fa(int x){
  if(x==fa[x])return x;
  int fx=get_fa(fa[x]);
  dis[x]+=dis[fa[x]];
  return fa[x]=fx;
}
void Merge(int x,int y){
  int fx=get_fa(x),fy=get_fa(y);
  fa[fx]=fy;
  dis[fx]+=num[fy];
  num[fy]+=num[fx];
  num[fx]=0;
  return ;
}
int main(){
  freopen("1196.in","r",stdin);
  freopen("1196.out","w",stdout);
  int t;
  cin>>t;
  for(int i=1;i<=3e5;i++){
    fa[i]=i;
    num[i]=1;
    dis[i]=0;
  }
  while(t--){
    char op;
    cin>>op;
    switch(op){
      case 'M':{
        int x,y;
        cin>>x>>y;
        Merge(x,y);
        break;
      }
      case 'C':{
        int x,y;
        cin>>x>>y;
        int fx=get_fa(x),fy=get_fa(y);
        if(fx!=fy)puts("-1");
        else cout<<abs(dis[x]-dis[y])-1<<endl;
        break;
      }
    }
  }
  //cout<<dis[2]<<' '<<dis[4]<<endl;
  return 0;
}
posted @   paper_plane  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示