通过这个题目,学习了下并查集的使用,详细的介绍在《算法导论》上。 并查集有三个基本操作,makeset(建立一个集合),find(找到某个元素所在集合的代表元素),union(合并两个集合)。 根据启发式策略的不同,在实现上略有差异。 #include <iostream> using namespace std; struct Node { int parent; //指向父节点 int count;//记录以其为代表的集合的元素的个数。union操作时有用,启发式策略。对于该题,可以方便输出最后结果。 }; Node person[30005]; int n,m,k; int Find(int a) /返回根节点(代表节点) { while(person[a].parent!=a) a=person[a].parent; return a; } int Union(int a,int b) //返回根节点(代表节点) { while(person[a].parent!=a) a=person[a].parent; while(person[b].parent!=b) b=person[b].parent; if(person[a].count>person[b].count) { person[b].parent=a; person[a].count+=person[b].count; return a; } else { person[a].parent=b; person[b].count+=person[a].count; return b; } } void Init() { for(int i=0;i<n;i++) { person[i].parent=i; person[i].count=1; } } int main() { int temp,temp2; while(scanf("%d%d",&n,&m)&&(n!=0||m!=0)) { Init(); for(int i=0;i<m;i++) { scanf("%d",&k); scanf("%d",&temp); for(int j=1;j<k;j++) { scanf("%d",&temp2); if(Find(temp)!=Find(temp2)) temp=Union(temp,temp2); } } printf("%d/n",person[Find(0)].count); } return 0; }