1.题目大意描述:
题目链接
某一个学校存在0-N-1名学生,0号学生已经确认患病,我们会给出如下数据
首先每组数据会开始输入两个数,第一个n代表学校的学生的数目,第二个m代表学校的社团的数目
接下来m行代表m个社团的成员的情况,(注意接下来的每行的第一个数字代表社团的成员的数目,后面的数字是成员的编号)
我们现在需要确认学校中有多少人确认患病
2.算法:
利用并查集我们来确认同一族谱中的父子关系
思路如下,我们对于下面的m行进行处理,第一个编号不管,我们从后面开始每一次将其和前一个的编号进行合并操作
最后我们从头遍历一遍所有的学生编号,如果发现和0号患者是同一族谱的,我们将计数器累计(注意,开始计数器的值是1,因为计算0号病患)
3.AC代码:
- #include"iostream"
- #include"cstdio"
- #include"cstdlib"
- #include"cstring"
- #define N 30100
-
- using namespace std;
-
- int fa[N];
- int deep[N];
- int n,m;
-
- void init()
- {
- for(int i=0;i<n;i++)
- {
- fa[i]=i;
- deep[i]=1;
- }
- }
-
- int find(int x)
- {
- if(fa[x]==x) return x;
- else return fa[x]=find(fa[x]);
- }
-
- void unit(int x,int y)
- {
- x=find(x);
- y=find(y);
- if(x==y) return ;
- else
- {
- if(deep[x]>deep[y]) fa[y]=x;
- else
- {
- fa[x]=y;
- if(deep[x]==deep[y]) deep[y]++;
- }
- }
- }
-
- bool same(int x,int y)
- {
- return find(x)==find(y);
- }
-
- int main()
- {
- while(scanf("%d%d",&n,&m)==2&&(n+m)!=0)
- {
- init();
- for(int i=1;i<=m;i++)
- {
- int p;
- cin>>p;
- int* data=new int[p+5];
- for(int i=1;i<=p;i++) cin>>data[i];
- for(int i=2;i<=p;i++) unit(data[i],data[i-1]);
- delete[] data;
- }
- int count=1;
- for(int i=1;i<n;i++)
- {
- if(same(0,i)) count++;
- }
- cout<<count<<endl;
- }
- return 0;
- }