并查集-银河英雄传说(nkoj1206)

并查集-银河英雄传说(nkoj1206)

题意分析

节点合并和查询是否在同一堆操作,同时维护节点间距,使用带序号的并查集

并查集(带序号)

首先了解并查集解决的问题:动态连通性问题,即把p和q所在的堆合并,看p和q在不在同一堆

首先让所有的点分属不同的组:father[i]=i

然后最naive的基本操作:

    int get_father(int x) {
        father[x] = get_father(father[x]);
    }

    void merge(int x, int y) {
        father[get_father(x)] = get_father(y);
    }

然后几种可能的拓展操作:

  • 维护堆大小(合并的时候父亲的堆增大)
    void merge(int x, int y) {
        x = get_father(x);
        y = get_father(y);
        if (x != y) {
            father[x] = y;
            size[y] += size[x];
        }
    }
  • 维护序号(合并的时候儿子的rank变大,get_father时在路径压缩前更新rank)
    int get_father(int x) {
        if (father[x] == x) {
            return x;
        } else {
            int tmp = get_father(father[x]);
            rank[x] += rank[father[x]];
            father[x] = tmp;
            return father[x];
        }
    }

    void merge(int x, int y) {
        x = get_father(x);
        y = get_father(y);
        if (x != y) {
            father[x] = y;
            rank[x] += size[y];
            size[y] += size[x];
        }
    }

本题维护序号即可,rank之差即是节点间距

代码

//
// Created by rv on 2018/4/20.
//

#include "iostream"
#include "cstdio"

using namespace std;
int T, i, j;
char ins;

struct UF {
    int count;
    int* father;
    int* size;
    int* rank;
    UF(int t) {
        count  = t;
        father = new int[t];
        size = new int[t];
        rank = new int[t];
        for (int i = 0; i < t; i++) {
            father[i] = i;
            size[i] = 1;
            rank[i] = 0;
        }
    }
    int get_father(int x) {
        if (father[x] == x) {
            return x;
        } else {
            int tmp = get_father(father[x]);
            rank[x] += rank[father[x]];
            father[x] = tmp;
            return father[x];
        }
    }
    void merge(int x, int y) {
        x = get_father(x);
        y = get_father(y);
        if (x != y) {
            father[x] = y;
            rank[x] += size[y];
            size[y] += size[x];
        }
    }
    int call(int x, int y) {
        if (get_father(x) != get_father(y)) {
            return -1;
        } else {
            return abs(rank[x] - rank[y]) - 1;
        }
    }
    void print() {
        printf("father: ");
        for (int i = 0; i < count; i++) {
            printf("%d ", father[i]);
        }
        printf("\n");
        printf("size: ");
        for (int i = 0; i < count; i++) {
            printf("%d ", size[i]);
        }
        printf("\n");
        printf("rank: ");
        for (int i = 0; i < count; i++) {
            printf("%d ", rank[i]);
        }
        printf("\n");
    }
};

int main() {
//    freopen("1206/data2.in", "r", stdin);
//    freopen("data2.out", "w", stdout);
    scanf("%d", &T);
    UF uf(T + 1);
    while(T--) {
        scanf("%s%d%d", &ins, &i, &j);
//        printf("%c %d %d\n", ins, i, j);
        if (ins == 'M') {
            uf.merge(i, j);
        }
        if (ins == 'C') {
            printf("%d\n", uf.call(i, j));
        }
//        uf.print();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xenoncat/article/details/80067895