链接:
https://www.nowcoder.com/acm/contest/106/C
来源:牛客网
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
It’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
并查集应用,难点在于删除操作,这一个操作影响了整道题目,一般并查集是没有删除操作的,这里出现了,所以这道题还是有点意义的。那么这个删除操作是怎么做的?题目只说了删除,但并没有说删除了这棵树,这棵树属于哪一片森林,所以我们当删除了这个树后,我们直接把这棵树当成一颗新树去处理,利用cur[i]去记录当前位置,所以cur[i]就代表了i所在的位置,如果没有这个cur[i]数组,直接用父节点去替换后面的树的话,那么就变成合并操作了。例如说
1 1 2
2 2
那么第2颗树就就给它新开一个树林,cur[2]=N,这个N代表了新树的位置,所以我们在第二颗树的时候,直接找到cur[2]就可以找到它现在所在的位置了。
我认为,其实这道题就是转移集合的问题。
#include <iostream> #include <cstring> #include <cmath> #include <cstdio> #include <algorithm> using namespace std; int father[100009*4]; int sum[100009*4]; int cur[100009*4]; int N; int Find(int x) { if(father[x]!=x) father[x]=Find(father[x]); return father[x]; } int Union(int a,int b) { int x=Find(cur[a]);//应该是直接当前的下标 int y=Find(cur[b]);//因为树删除后是会变掉的 if(x!=y) { father[x]=y; sum[y]+=sum[x]; } return 0; } int main() { int t,Count=1; scanf("%d",&t); while(t--) { int n,m,i,j,k,a,b,x,y; scanf("%d%d",&n,&m); printf("Case #%d:\n",Count++); for(i=1; i<=n+m+10; i++) { father[i]=i; cur[i]=i;//当成独立的当前树的位置 sum[i]=1; } N=n; while(m--) { scanf("%d",&i); if(i==1) { scanf("%d%d",&a,&b); Union(a,b); } else if(i==2) { scanf("%d",&a); x=Find(cur[a]); sum[x]--; N++; cur[a]=N; } else if(i==3) { scanf("%d",&a); x=Find(cur[a]); printf("%d\n",sum[x]); } else if(i==4) { scanf("%d%d",&a,&b); x=Find(cur[a]); y=Find(cur[b]); if(x==y) { printf("YES\n"); } else { printf("NO\n"); } } } } }