[NOI2002] 银河英雄传说

题目链接:

点我

题目分析:

带权并查集的题,记一个\(d\)数组维护每个战舰前面有多少战舰,再在每个树根上记录一个集合大小\(sum\),每次进行\(get_father\)的时候维护一下\(d\)数组,合并的时候更新集合大小。由于写了路径压缩,每次合并的时候还要把之前集合的\(sum\)更新到\(d\)数组上。

代码:

#include<bits/stdc++.h>
#define N (1000000+5)
using namespace std;
inline int read(){
    int cnt=0,f=1;char c;
    c=getchar();
    while(!isdigit(c)){
        if(c=='-') f=-f;
        c=getchar();
    }
    while(isdigit(c)){
        cnt=cnt*10+c-'0';
        c=getchar();
    }
    return cnt*f;
}

int t,fa[N],d[N],sum[N],x,y;
char c;

int get_father(int x){
    if(fa[x]==x)return x;
    int root=get_father(fa[x]);
    d[x]+=d[fa[x]];
    return fa[x]=root;
}

void merge(int x,int y){
    int a=get_father(x);
    int b=get_father(y);
    fa[a]=b;d[a]=sum[b];
    sum[b]+=sum[a];
}

int query(int x,int y){
    int a=get_father(x);
    int b=get_father(y);
    if(a!=b) return -1;
    else {
    int ans=abs(d[x]-d[y])-1;
    return ans;
    }
}

int main(){
    t=read();
    for(register int i=1;i<=30001;i++) fa[i]=i,d[i]=0,sum[i]=1;
    for(register int i=1;i<=t;i++) {
        cin>>c;x=read();y=read(); 
        if(c=='M') merge(x,y);
        if(c=='C') printf("%d\n",query(x,y));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/kma093/p/10328565.html