牛客Professional Manager(并查集)

t’s universally acknowledged that there’re innumerable trees in the campus of HUST. 

Thus a professional tree manager is needed. Your task is to write a program to help manage the trees. 
Initially, there are n forests and for the i-th forest there is only the i-th tree in it. Given four kinds of operations.

1 u v, merge the forest containing the u-th tree and the forest containing the v-th tree;

2 u, separate the u-th tree from its forest;

3 u, query the size of the forest which contains the u-th tree;
4 u v, query whether the u-th tree and the v-th tree are in the same forest.

输入描述:

The first line contains an integer T, indicating the number of testcases.

In each test case:

The first line contains two integers N and Q, indicating the number of initial forests and the number of operations.

Then Q lines follow, and each line describes an operation.

输出描述:

For each test cases, the first line should be "Case #i:", where i indicate the test case i.
For each query 3, print a integer in a single line.
For each query 4, print "YES" or "NO" in a single line.

示例1

输入

1
10 8
3 1
4 1 2
1 1 2
3 1
4 1 2
2 1
3 1
4 1 2

输出

Case #1:
1
NO
2
YES
1
NO

这是一道有点宇宙不同的并查集模板题,与其他不同的是多了个删除操作,那么我们该怎么做呢? 可以想到的是直接把要删除的点的父亲结点改成是自己,但是,如果这个点有子节点怎么办? 很显然,这种方法就无法做了,
我们可以给每个点都给他们一个编号,删除点,就相当于该点的编号改变就可以了,也是相当于构造新点
AC代码
#include<stdio.h>
int n,f[200001],d[200001],h[200001],now;
///f为并查集,d为编号,h为高度
int findd(int x)///查找父节点
{
    if(f[x]!=x)
        f[x]=findd(f[x]);
    return f[x];

}
void init ()
{
    for(int k=1 ;k<=n ;k++)
    {
        f[k]=k;
        d[k]=k;
        h[k]=1;
    }
}
///合并
void HB(int u,int v)
{
        u=d[u],v=d[v];
        u=findd(u),v=findd(v);
        if(u==v)
        return ;
        f[u]=v;
        h[v]+=h[u];
}
///删除
void SC(int u)
{
    int v;
     v=d[u];
    v=findd(v);
    h[v]--;
    ++now;
    d[u]=now;
    f[now]=now;h[now]=1;
}

int main()
{
    int t,i,q,x,v,u;
    scanf("%d",&t);
    for(i=1 ;i<=t; i++)
    {
        printf("Case #%d:\n",i);
        scanf("%d%d",&n,&q);
        now=n;
        init();
        while(q--)
        {
            scanf("%d",&x);
            if(x==1)
            {
                scanf("%d%d",&u,&v);
                HB(u,v);

            }
            if(x==2)
            {
                scanf("%d",&u);
               SC(u);

            }
            if(x==3)
            {
                scanf("%d",&u);
                u=d[u];u=findd(u);

                printf("%d\n",h[u]);

            }
            if(x==4)
            {
                scanf("%d%d",&u,&v);
                u=d[u];v=d[v];
                u=findd(u);v=findd(v);
                if(u==v)
                    printf("YES\n");
                else
                    printf("NO\n");
            }

        }
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/shuaihui520/p/8974030.html