#include<iostream>
using namespace std;
int fa[10009];//10^4 4个0后面
bool exist[10009]={false};
int book[10009]={0};//记录每棵树的个数,只有根可以在里面进行赋值,赋值为其数目
int findfa(int x){
int a=x;
while(x!=fa[x]){
x=fa[x];
}
while(a!=fa[a]){
int z=a;
a=fa[a];
fa[z]=x;
}
return x;
}
void unionn(int a,int b){
int faz=findfa(a);
int fbz=findfa(b);
if(faz!=fbz){
fa[faz]=fbz;
}
}
int main(){
int n,_1,_2,_3;
//并查集一开始最重要的一步,初始化集合
for(int i=0;i<10009;i++){
fa[i]=i;//根节点是他自己
}
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d",&_1,&_2);//先输入一个结点
exist[_2]=true;
for(int j=1;j<_1;j++){
scanf("%d",&_3);
unionn(_2,_3);
exist[_3]=true;
}
}
for(int i=0;i<10009;i++){
if(exist[i]==true){
int root=findfa(i);//函数变量用圆括号
book[root]++; //不应该是找他的父节点而是要找他的根找到他祖坟上去哈哈
}
}
int sumtr=0,sumbir=0;
for(int i=0;i<10009;i++){
if(book[i]>0){
sumtr++;
sumbir+=book[i];
}
}
printf("%d %d\n",sumtr,sumbir);
int m,temp1,temp2;
scanf("%d",&m);
for(int i=0;i<m;i++){
scanf("%d%d",&temp1,&temp2);
if(fa[temp1]==fa[temp2])printf("Yes\n");
else printf("No\n");
}
return 0;
}
总结
1.10^4 4个0不是一共 4位
2.注意路径压缩的查找根节点的方式 根节点是fa【x】=x的下标,并查集一开始就要初始化,每一个元素都是自己的根节点,并的操作颠倒赋值也没有关系,exist存在数组,book 数组,记录根的数量以及每棵树的结点的个数,要寻根不是结点的父节点,同时合并操作时先读一个结点作为合并的基结点后面的东与这个节点合并
3.并查集实际上针对的问题是本来属于同一集合的元素,题目中给你分开了,你要重新把它们合并在一起然后处理
英语
问题 无