题目描述:Ignatius,这个人过生日,然后请了很多朋友来聚会,然后并不是他的所有的朋友都互相认识,现在给出他的朋友们相互认识的情况,并且规定,如果1认识2,2认识3,则1认识3,要求每一伙认识的朋友坐在一张桌子上,然后要求一共需要多少张桌子。
解题报告:此题我用的是并查集,也就是将每次输入的一对关系都放到一个集合里面,然后最后将所有的认识的关系压缩到一个节点下,同通俗的说就是把一伙互相认识的人都归到其中一个人的名下,然后统计有多少伙人就可以了。中间有一个压缩路径的操作,不好讲,看代码就知道了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 const int MAX = 1000+5; 5 6 int T,a,b,N,M,prim[MAX]; 7 int find(int k) { 8 return prim[k]==k? k:(prim[k] = find(prim[k])); 9 } 10 11 12 int main() { 13 scanf("%d",&T); 14 while(T--) { 15 scanf("%d%d",&N,&M); 16 for(int i = 1;i<=N;++i) 17 prim[i] = i; 18 for(int i = 0;i<M;++i) { 19 scanf("%d%d",&a,&b); 20 if(a>b) 21 std::swap(a,b); 22 prim[find(a)] = find(b); 23 } 24 for(int i = 1;i<=N;++i) //这一步压缩路径,必要 , 25 //将所有在一个集合内的元素压缩成所有前去节点相同 26 find(i); 27 std::sort(prim+1,prim+N+1); 28 int tot = 0; 29 int c = -1; 30 for(int i = 1;i<=N;++i) 31 if(prim[i]!=c) { 32 c = prim[i]; 33 tot++; 34 } 35 printf("%d ",tot); 36 } 37 return 0; 38 }