HDU 3635 Dragon Balls(并查集)

题目链接:HDU 3635 Dragon Balls

并查集。

这是我第一次见到需要改动find函数的并查集题目,对并查集有了更深入的认识。

每次移动后遍历改变转移次数必然超时,无论是所有节点全部遍历还是用set优化一下。

每个并查集都必有p[u] = v,然后想到是否可以仅改变tra_num[u]的值,在纸上画了画确实可以。每次把tra_num[u]加1,其实每个根节点只能作为根节点移动一次,剩下的移动均是作为非根节点移动的,最后统计一个龙珠转移过几次时候find一次,途中更新当前龙珠的tra_num为本身加上父龙珠的tra_num。

这题用cin,cout会TLE。至于为什么需要getchar(),看这里。

#include <iostream>
#include <stdio.h>

using namespace std;

const int MAX_N = 10000 + 100;
int t, n, m, tra_num[MAX_N], balls_num[MAX_N], p[MAX_N];

int _find(int x)
{
    if(p[x] == x)
        return x;
    else
    {
        int temp = p[x];
        p[x] = _find(p[x]);
        tra_num[x] += tra_num[temp];
        return p[x];
    }
}
int main()
{
    scanf("%d", &t);
    int cnt = 0;
    while(t--)
    {
        printf("Case %d:\n", ++cnt);
        char q;
        int a, b, u, v;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++)
        {
            p[i] = i;
            tra_num[i] = 0;
            balls_num[i] = 1;
        }

        for(int i  = 0;i < m;i++)
        {
            getchar();
            scanf("%c", &q);
            if(q == 'T')
            {
                scanf("%d%d", &a, &b);
                u = _find(a);
                v = _find(b);
                if(u != v)
                {
                    p[u] = v;
                    tra_num[u]++;
                    balls_num[v] += balls_num[u];
                    balls_num[u] = 0;
                }
            }
            else if(q == 'Q')
            {
                scanf("%d", &a);
                u = _find(a);
                printf("%d %d %d\n", u, balls_num[u], tra_num[a]);
            }
        }
    }
    return 0;
}



你可能感兴趣的:(HDU 3635 Dragon Balls(并查集))