acwing 238. 银河英雄传说

传送门

带边权的并查集

#include

using namespace std;
const int N = 1e6+10;

int f[N], num[N], d[N];
///d[i]表示i到祖宗的距离,num[i]表示以i为祖宗的队列的长度,是否清零都可以,因为合并后就用不到了

int Find(int x)
{
    if(x == f[x]) return x;
    int root = Find(f[x]);
    d[x] += d[f[x]];  ///更新祖先,并同时更新x到祖先的距离
    f[x] = root;
    return root;
}

void merge(int x, int y) ///把x所处的队列放在y所处的队列后面
{
    x = Find(x), y = Find(y);
    if(x == y) return ;
    f[x] = y;          ///更改x的祖先为y
    d[x] += num[y];   ///更新x到祖先的距离,就是原距离加上以y为祖先的队列的长度
    num[y] += num[x]; ///把x的数量加到y为祖先的队列中
    num[x] = 0;
} 

int main()
{
    int T;
    cin>>T;
    for(int i = 1; i <= N; ++i) f[i] = i, num[i] = 1;
    while(T--)
    {
        string op;
        int x, y;
        cin>>op>>x>>y;
        if(op[0] == 'M') merge(x, y);
        else{
            int tx = Find(x), ty = Find(y);
            if(tx != ty) puts("-1");
            else printf("%d\n", max(abs(d[x]-d[y])-1, 0));
        }
    }
    return 0;
}

你可能感兴趣的:(并查集)