【ZCMU1930】帽子戲法(並查集)

題目鏈接

1930: 帽子戲法

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 88  Solved: 24
[Submit][Status][Web Board]

Description

小A家有很多很多頂帽子初始時帽子都是獨立分開的,每頂帽子都有一個編號用於區分.小A會有以下操作之一:
1.將編號爲y的帽子所在的帽子堆放在編號爲x的帽子所在的帽子堆頂上,如果x,y在同一堆則不做任何動作.
2.小A會向你詢問編號爲x的帽子上方有多少隻帽子.

 

Input

輸入有多組數據:
第一行輸入N,M分別爲帽子數和操作數(1<=N<=40000,1<=M<=400000)
帽子的編號對應1,2,3...,N.
接下來有M行輸入爲 T x y 對應操作1. Q x 對應操作2.

 

Output

對於小A的詢問輸出位於編號爲x的帽子上方的帽子數.

 

Sample Input

2 2

T 1 2

Q 1

Sample Output

1

HINT

 

Source

lcf

 

【解題思路】

num[i]:每個帽子上的帽子數

pos[i]:每個帽子堆的帽子數,i 是這堆帽子的最上面的帽子編號

需要注意的是在每一次合併的時候是把兩個根節點合併,也就是說num數組只更新該點到根節點那條路徑上的值,但是根節點的其他兒子節點並沒有被更新,所以在查詢的時候,需要再用並查集遍歷一遍查詢節點的路徑上的num。

【代碼】

#include<bits/stdc++.h>
using namespace std;
const int maxn=4e5+5;
int pre[maxn],num[maxn],pos[maxn];
//num表示每個帽子上的帽子數 pos表示每個帽子堆的帽子數
int findroot(int x)
{
    if(x!=pre[x])
    {
        int fx=pre[x];
        pre[x]=findroot(pre[x]);
        num[x]+=num[fx];
    }
    return pre[x];
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=0;i<=n;i++)
        {
            pre[i]=i;
            num[i]=0;
            pos[i]=1;
        }
        while(m--)
        {
	    char ch=getchar();
	    while(ch!='T'&&ch!='Q')ch=getchar();
            if(ch=='T')
            {
                int x,y;
                scanf("%d%d",&x,&y);
                int fx=findroot(x),fy=findroot(y);
                if(fx!=fy)
                {
                    pre[fx]=fy;
                    num[fx]+=pos[fy];
                    pos[fy]+=pos[fx];
                }
            }
            else
            {
                int x;
                scanf("%d",&x);
                findroot(x);
                printf("%d\n",num[x]);
            }
        }
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章