P1196 [NOI2002]银河英雄传说-(边带权并查集)

利用路径压缩来统计每个节点到树根之间路径上的一些信息(边带权)

题目链接
以前做这个题的时候,一直有一个疑问,为啥要开两个数组,一个dis[]那是应该的,为什么还得加一个Size[]数组呢,当我其他的题的发现其实一个dis[]就可以了,为啥这里不行?
这个题的特殊点就是两棵树合并的时候,x的祖先接在y的树的叶子结点。但是y所在的树,y不一定是这棵树的叶子结点,造成dis[x的祖先]更新没办法实现,所以引入了Size[],它的功能不仅知道这个棵树的结点数量,同时也代表这个树的叶子结点到根的距离,这题的特殊点,这棵树一定是一个队列,也就是线性的。

const int N=3e5+5;
int fat[N],dis[N],Size[N];
int find(int x)
{
    if(fat[x]==x)
        return x;
    int root=find(fat[x]);
    dis[x]+=dis[fat[x]];
    return fat[x]=root;
}
signed main()
{
    IOS;
    //file();
    for(int i=1;i<=3e4;i++)
        fat[i]=i,dis[i]=0,Size[i]=1;
    int t;
    cin>>t;
    while(t--)
    {
        char a;
        int b,c;
        cin>>a>>b>>c;
        int tb=find(b);
        int tc=find(c);
        if(a=='M')
        {
            fat[tb]=tc;
            dis[tb]+=Size[tc];
            Size[tc]+=Size[tb];
        }
        else
            cout<<(tb==tc?abs(dis[b]-dis[c])-1:-1)<<endl;
    }
    return 0;
}
发布了130 篇原创文章 · 获赞 5 · 访问量 4995

猜你喜欢

转载自blog.csdn.net/weixin_44224825/article/details/104239797
今日推荐