本文主要是介绍【并查集】POJ1611-The Suspects + 并查集简单理解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
今天讲的新东西是并查集啦~因为以前看过一个特别好理解的介绍并查集的文章,所以今天还挺能理解的。。。推荐给大家,顺便我也做个马克。。。
链接:高级数据结构设计--并查集及实现学习笔记(有趣篇) - ACShiryu - 博客园
另外里面也有一些相关的题,可以看一看!
其实要是光把部分的代码放上去看不懂还是并没有什么卵卵用,来道相对(没错就是相对)典型的简单的题吧!
来人,上题!
【题目】
Time Limit: 1000MS | Memory Limit: 20000K | |
Description
In the Not-Spreading-Your-Sickness University (NSYSU), there are many student groups. Students in the same group intercommunicate with each other frequently, and a student may join several groups. To prevent the possible transmissions of SARS, the NSYSU collects the member lists of all student groups, and makes the following rule in their standard operation procedure (SOP).
Once a member in a group is a suspect, all members in the group are suspects.
However, they find that it is not easy to identify all the suspects when a student is recognized as a suspect. Your job is to write a program which finds all the suspects.
Input
A case with n = 0 and m = 0 indicates the end of the input, and need not be processed.
Output
Sample Input
100 4 2 1 2 5 10 13 11 12 14 2 0 1 2 99 2 200 2 1 5 5 1 2 3 4 5 1 0 0 0
Sample Output
4 1 1
Source
【题意】
就是说一个学校有很多社团,一天0号同学感染了SARS,而且和0号同学同在一个社团的人都会被感染,被感染的同学如果参加了其它社团,那么其他同学参加的社团所有成员都会被感染,以此类推,给你这个学校的社团成员名单,问共有多少同学被感染。
输入有若干测试实例,数据以n和m都为0时结束,第一行第一个数字n是该学校参加社团同学的总人数,第二个m表示有m个社团,下面m行第一个数字表示每个社团的人数,后面表示每个社团的成员学号。
输出占一行,输出被感染同学人数。
【思路】
之所以选这道题,是因为它能较独立地展现两个(三个?)并查集里面常用的函数或者说技巧。这道题说白了主要分为以下几步:把每个社团的成员分别铁索连环起来并统计社团人数,把有同一个同学参加的几个社团铁索连环并趁机统计总人数,找到0所在的社团,找到与0联动的最顶层同学编号,这位同学此时是所有被感染的同学的头头,此时只要将这位同学所对应的人数计数器显示出来就行了,这其中对应两个函数:find():用来查找最高的同学;Union():铁索连环社团成员/各个社团;另外要加一个num[]数组来实时记录总人数。具体还是要看代码中我的注释:
【代码】
#include<cstdio>int n,m,form,latt,a[30001],num[30001];//num数组用来记录社团人数,一开始没组社团时每个人自成一队每个人对应的num都是1,当有两个人合并时将两个人对应的num加起来
void chongzhi();
int find(int x);
void Union(int p,int q);int main()
{while(scanf("%d%d",&n,&m)&&(n||m)){chongzhi();//重置数据 for(int i=0;i<m;i++){int nn;scanf("%d",&nn);for(int j=0;j<nn;j++){if(j==0){scanf("%d",&form);continue;}scanf("%d",&latt);//输入,每行第一个数表示成员个数 Union(form,latt);}}printf("%d\n",num[find(0)]);}
}void chongzhi()
{for(int i=0;i<=n;i++){a[i]=i;num[i]=1;}
}int find(int x)
{return a[x]==x?x:a[x]=find(a[x]);//查找根节点
}void Union(int p,int q)
{int root1=find(p);int root2=find(q);if(root1!=root2){a[root2]=root1;//此时root1是老大 num[root1]+=num[root2];//把两个社团的人数合并为一个社团 }<span style="font-family: Arial, Helvetica, sans-serif;">}</span>
BilngBilng收工啦~
这篇关于【并查集】POJ1611-The Suspects + 并查集简单理解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!