这道题自己写的在自己机子上通过了,但提交的时候还是错误,和别人的代码对照了一下,发现就是判断父节点的条件没写好.网上有不少关于并查集的介绍,随手百度一下就行.我自己没有详细介绍并查集是怎么实现的,并不是自己不想分享知识,而是自己的水平差的太远,还有csdn的博客上传图片非常坑,但自己确实在网上学习了不少的东西.对于acm新手来说,坚持和自学是必须的.
对于代码的理解最好自己手写运算一遍.
#include<iostream> #include<cstdio> using namespace std; //厉害,在读取完k后,利用for来合并 #define MAX 30010 #define MAXN 550 int father[MAX],son[MAX]; int i,j;//循环变量 void Uset(int n)//初始化father[]和son[],如:father[2]=1;说明2的父节点是序号1.son[1]=3,是说序号1的共有3个节点,包括自身. { for(i=0;i<n;i++) { father[i]=i; son[i]=1; } } int find(int x)//寻找父节点 { return (x == father[x] ? x :find(father[x])); } void Union(int x,int y)//合并运算 { int root1=find(x); int root2=find(y); if(root1!=root2)//我自己错在这里了 { father[root2]=root1; son[root1]+=son[root2]; } // else // { // father[root1]=root2; // son[root2]+=son[root1]; // } } int main() { int n,m,k,a,b,c;// freopen("1611.txt","r",stdin); while(1) { scanf("%d%d",&n,&m); if(n==0 && m==0) break; Uset(n); while(m--) { cin>>k>>a; for(i=1;i<k;i++)//怎样区分0? { scanf("%d",&b); Union(a,b); } } printf("%d\n",son[find(0)]);//真厉害,程序的美丽或许正在于此,记 //son永远在找下属集合 } return 0; }