牛客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; }