AcWing 837. 连通块中点的数量
原题链接
简单
作者:
腾杨天下
,
2021-04-06 07:56:37
,
所有人可见
,
阅读 168
需要跟836.合并集合区分开来的点
- 主要这道题跟合并集合那道题的不同之处就在于这道题需要记录每个集合当中元素的数量,还有就是可能会让同一棵树当中的子节点之间连边甚至是连自环,这是毫无意义的行为,需要无视(continue)。
- 记录集合中元素数量的操作很简单,只要使用size[]数组来存一下就可以了,然后进行树合并的时候,要把作为父树
的size值加上作为子树的size值
c++代码
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int p[N],sz[N];
int find(int x)
{
if(p[x]!=x)p[x]=find(p[x]);//依旧是优美的查找祖宗节点+压缩路径,只用了两
return p[x];//行就解决,神之妙笔!!!!
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
p[i]=i;
sz[i]=1;
}
while(m--)
{
string cma;
cin>>cma;
if(cma=="C")
{
int a,b;
cin>>a>>b;
if(find(a)==find(b))continue;//题目有可能让我们在一个连通块内的两个节点之间连边,也有可能
//在同一个节点上连自环,这样的操作是没有意义的,直接无视就好
sz[find(b)]+=sz[find(a)];//让a树作为枝接到b树上,b树祖宗节点编号为下标记录的size值就要加上
//原a树祖宗节点编号为下标记录的size值了,注意这个步骤绝对绝对不能把ab写反了!!!!
p[find(a)]=find(b);//让原a树祖宗节点的父节点指向b树的祖宗节点
}
else if(cma=="Q1")
{
int a,b;
cin>>a>>b;
if(find(a)==find(b))cout<<"Yes"<<endl;//没什么难的,就查询一下,不讲了
else cout<<"No"<<endl;
}
else if(cma=="Q2")
{
int a;
cin>>a;
cout<<sz[find(a)]<<endl;//没什么难的,就输出一下,不讲了
}
}
return 0;
}