NOI_2002银河英雄传说

  • 题目链接:[NOI2002]银河英雄传说
  • 题目思路: 根据题意,这道题明显要用带权并查集,我们用size数组表示一个集合内的容量,d[i]表示元素i之前的元素数量,我们可以在find()函数和合并过程中来维护d[]数组,具体解释见代码。
  • 代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define gc getchar()
    #define Maxn 30010
    using namespace std;
    int sc() {
    int xx = 0, ff = 1; char cch;
    while (cch < '0' || cch > '9') {
    if (cch == '-') ff = -1; cch = gc;
    }
    while (cch >= '0'&& cch <= '9') {
    xx = (xx << 1) + (xx << 3) + (cch ^ '0'); cch = gc;
    }
    return xx * ff;
    }
    int t;
    int fa[Maxn], size[Maxn], d[Maxn];
    int find( int x) {
    if (x == fa[x]) return x;
    int xx = find( fa[x]);
    d[x] += d[fa[x]];
    return fa[x] = xx;
    }
    int aabs(int x) {
    return x > 0 ? x : - x;
    }
    int main() {
    t = sc();
    for (int i = 1; i <= 30000; i++) { //赋初值,size数组为1
    fa[i] = i;
    size[i] = 1;
    }
    for (int i = 1; i <= t; i++) {
    char c[2];
    cin >> c[0];
    int x = sc(), y = sc(); //一定要在合并前find(),因为find()函数不仅是找爸爸,还要维护d数组!!!
    int xx = find( x);
    int yy = find( y);
    if (c[0] == 'M') {
    // cout << xx << " "<< yy << endl;
    fa[xx] = yy;
    d[xx] = size[yy];
    size[yy] += size[xx]; //注意我这样合并yy是父亲,则要把xx的元素数加到yy上
    }
    else {
    // int x = sc(), y = sc();
    // cout << fa[x] << " " << fa[y] << endl;
    if(fa[x] == fa[y])
    printf ("%d\n", aabs( d[x] - d[y]) - 1); //两艘战舰之间的数目不难推出为|d[x]-d[y]|-1
    else
    printf ("-1\n");
    }
    }
    return 0;
    }
rp++