The Suspects(并查集)

tech2024-08-19  45

题目链接

Description

Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recognized as a global threat in mid-March 2003. To minimize transmission to others, the best strategy is to separate the suspects from others. 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

The input file contains several cases. Each test case begins with two integers n and m in a line, where n is the number of students, and m is the number of groups. You may assume that 0 < n <= 30000 and 0 <= m <= 500. Every student is numbered by a unique integer between 0 and n−1, and initially student 0 is recognized as a suspect in all the cases. This line is followed by m member lists of the groups, one line per group. Each line begins with an integer k by itself representing the number of members in the group. Following the number of members, there are k integers representing the students in this group. All the integers in a line are separated by at least one space. A case with n = 0 and m = 0 indicates the end of the input, and need not be processed.

Output

For each case, output the number of suspects in one line.

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

这道题的大致意思是给你n和m,n代表有0~n-1编号的学生,m代表有m个社团,其中这0号同学感染了SARS,在相同社团的人会被传染,要求你统计有多少个人被传染了? 我的思路是首先你去统计这些同学加入了哪些社团,给它进行标记如果有一个同学加入了不同的社团,我就将它第一个标记的社团作为后标记社团的父亲结点。如果社团中有0的就存放另一个数组,然后去遍历这个数组和这m个社团,是否有相同的祖先结点,如果有,那么将这个社团的人放进set(去重),最后去算set中含有的元素个数。(set中0的时候需要输出1,即0号同学没加入任何社团)。 代码如下:

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<set> using namespace std; int fa[505];//社团的父亲结点数组 int len[505];//代表社团的人数 int a[30005];//代表社团的人 int ef[505][30005]; int e[505]; int flag[505]; int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]); } void baba(int x,int y){ int fx=find(x); int fy=find(y); fa[fx]=fa[fy]; } int main(){ int n,m; set<int>s; while(~scanf("%d%d",&n,&m)&&n+m){ s.clear(); for(int i=1;i<=m;i++)fa[i]=i; for(int i=1;i<=m;i++)flag[i]=0; for(int i=0;i<=n-1;i++)a[i]=-1; int cnt=0; for(int i=1;i<=m;i++){ scanf("%d",&len[i]); for(int j=1;j<=len[i];j++){ int b; scanf("%d",&ef[i][j]); if(a[ef[i][j]]==-1){ a[ef[i][j]]=i; } else { baba(a[ef[i][j]],i); } if(ef[i][j]==0){ e[++cnt]=i; } } } int sum=0; for(int i=1;i<=cnt;i++){ for(int j=1;j<=m;j++){ if(find(j)==find(e[i])){ flag[j]=1; } } } for(int i=1;i<=m;i++){ if(flag[i]){ // cout<<i<<endl; for(int j=1;j<=len[i];j++){ s.insert(ef[i][j]); } } } if(s.size())cout<<s.size()<<endl; else cout<<1<<endl; } }

道阻且长 自己选的路 跪着也要走完

最新回复(0)