“扩展域”与"边带权"的并查集

https://www.luogu.org/problemnew/show/P1196 

银河英雄传说

#include<bits/stdc++.h>
using namespace std;
const int maxn=30005;
int f[maxn],d[maxn],s[maxn]; // f[i]用来记录i节点的根 d[i]记录i所在集合的前面有几个节点 s[i]记录s所在集合中节点的总大小 
int n;
void init()//初始化
{
    for(int i=1; i<=30000; i++)
    {
        f[i]=i;
        d[i]=0;// 初始每个节点前面视为0,每个节点自成一个集合大小为1 
        s[i]=1;
    }
}
int getf(int a)
{
    if(a==f[a]) return a;
    int root=getf(f[a]);   
    d[a]+=d[f[a]]; // 在将a节点指向新的根节点时,将d[a]更新为从a到根的距离 
    return f[a]=root; // 压缩路径 
}
void merge(int a, int b)
{
    int t1,t2;
    t1=getf(a);
    t2=getf(b);  
    f[t2]=t1;//靠左原则,将t2合并到t1上
    d[t2]=s[t1];// 注意顺序 合并之后t1的大小为t1+t2的和,将d[t2]的距离更新为之前s[t1]的大小 
    s[t1]+=s[t2];
}
int main()
{
    init();
    int t;
    cin>>t;
    char c;
    int m,n;
    for(int i=1; i<=t; i++)
    {
        cin>>c>>m>>n;
        if(c=='C')
        {
            if(getf(m)!=getf(n))
                cout<<"-1"<<endl;
            else
                cout<<abs(d[m]-d[n])-1<<endl;// 战舰之间的距离为两者相减的绝对值再减1 
        }
        else
            merge(n,m);// 合并两列的战舰 
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/dongdong25800/p/10519904.html