题目大意就是啊病毒又开始发作了。。。
某学校的班级开始查哪些是有可能感染流感的人
学号是从0号开始的(奇葩设定)。。。
每个班的0号都有很大的可能感染了流感(0号忒倒霉了)。。
每个班级都有一些团伙,团伙里的人都很亲密(就有有1人感染,团伙里的其他人都会感染)
输入:
每组数据:
第一行:(班级人数)(团伙个数)
然后就是描叙每一个团伙:(团伙人数)(一些学号)
对于每组数据输出可能以感染的人
主题思路就是并查集啦·~~=。=
难点就是人数的统计了
我想不出有神马好方法,但我知道对于每一棵树(所有有关联的人)只要知道其总人数就行了
关于谁谁谁有关谁谁谁无关没有弄清楚的必要(这句话就是说可以路径压缩)
于是乎如果a和b有关,我们把a所在树和b所在树和在一起就行了
(就是把a的祖宗和b的祖宗合并)
最后输出0的祖宗所在树的元素数量
值得一提的是,又要对自己和自己合并做特殊处理(普通并查集不需要)
因为涉及到元素个数的合并~!
AC代码
#include <iostream> #include <cstdio> #include <cstdlib> using namespace std; #define MAX (30000+1) int n,m,t,mat,son,mot[MAX],num[MAX]; int find(int x) { if ( x != mot[x] ) { mot[x] = find(mot[x]); } return mot[x]; } int work() { for (int i = 0; i < n; i++) { mot[i] = i; num[i] = 1; } for (int i = 1; i <= m; i++) { scanf("%d",&t); if ( t < 1 ) { continue; } scanf("%d",&mat); mat = find(mat); for (int j = 1; j < t; j++) { scanf("%d",&son); son = find(son); if ( son != mat ) { mot[son] = mat; num[mat] += num[son]; } } } cout<<num[find(0)]; } int main() { scanf("%d %d",&n,&m); work(); while(1) { scanf("%d %d",&n,&m) if ( n == 0 && m == 0 ) { break; } cout<<endl; work(); } return 0; }