并查集合并到深度小的点,每次都选编号小的点做祖先即可。

为什么?因为题目说了,v能到u,即v是深度小的,从u和v路径上的点可以互相到达,用并查集合并即可。

#include <stdio.h>
#define N 200050
int n, m, i, j, k, a, b, p[N], f[N];
struct AB{
    int a, b, n;
} d[N];
int find(int x){
    if(x == f[x]) return x;
    return f[x] = find(f[x]);
}
int main(){
    scanf("%d", &n);
    for(i=1; i<=n; i++) f[i] = i;//强连通分量
    for(i=2; i<=n; i++){
        scanf("%d", &p[i]);//父亲
    }
    scanf("%d", &m);
    while(m--){
        scanf("%d%d", &k, &a);
        if(k == 1){
            scanf("%d", &b);
            a = find(a), b = find(b);
            while(find(a) != b){
                a = f[a];
                f[a] = find(p[a]);//深度小做祖先
            }//a和b不在同一个强连通分量,合并即可
        }
        else printf("%d\n", find(a));
    }
    return 0;
}

作者 crxis

发表回复