题目:
分析:这也是一道并查集的模板题,但是区别于上一道更简单的模板题----->上一题较简单模板题链接
我们这次需要使用路径压缩,因为题目数据比较大且符合路径压缩的需求,具体压缩方式如图:
我们将每个节点的父亲节点都让它成为这个集合的老祖宗节点,这样在遍历集合个数的时候就可以直接找到它的老祖宗是否一样来判定他们是否有血缘关系;具体内容如下代码实现:
#include"iostream"//本代码主要分析路径压缩,详细参照上述链接模板题
using namespace std;
const int N=1e6+5;
int fa[N];
int find_fa(int i){
/*递归实现路径压缩
if(fa[i]==i)
return fa[i];
else {
fa[i]=find_fa(fa[i]);
return fa[i];}
*/
while(fa[i]!=i)
{
fa[i]=fa[fa[i]];//注意理解这句话,分析fa[i]的变化情况,可以通过添加代码打屏幕上查看fa的变化
i=fa[i];//将i遍历到父亲的父亲节点上
}
return i;
}
int unionn(int x,int y){
int fa_a=find_fa(x);
int fa_b=find_fa(y);
if(fa_a!=fa_b){
fa[fa_a]=fa_b;
}
}
int main(){
int n,m,k;
cin>>n>>m;
for(int i=1;i<=n;i++) fa[i]=i;
while(m--){
int x, y;
cin>>x>>y;
unionn(x,y);
}
cin>>k;
while(k--){
int x,y;
cin>>x>>y;
if(find_fa(x)==find_fa(y))//对两个数据的老祖宗节点分析是否相同
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
for(int i=1;i<=n;i++) cout<<fa[i]<<endl;
return 0;
}
ps:我看到的较好的并查集分析博客园:
作者:CYJB
出处:http://www.cnblogs.com/cyjb/
GitHub:https://github.com/CYJB/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。