POJ 1611 The Suspects (并查集)
2016-03-18 11:27
357 查看
题目链接:
POJ 1611 The Suspects
题意:有n个学生,编号为0–n-1。有m个社团,每个社团有k位成员,接下来给出每位成员的编号,
如果一个社团里有一位成员感染了,那么这个社团的所有成员都被感染了。
已知编号为0的学生恒被感染。
问最终有多少位学生被感染了?
分析:
对于每一个社团成员除第一位成员外将所有成员都与第一位成员合并集合,最终只要查找和编号为0的学生公共祖先一样的学生人数即可。
有两种方法:
①:设一个数组num[maxn],num[i]表示以i为公共祖先的元素个数,最后只需输出num[0]。
②:输入合并完后,逐一统计和编号为0的嘘声公共祖先一样的学生人数。
注意:
1、在mix函数(合并操作)中,对两个集合合并时,要注意谁是谁的祖先(小数字是大数字的祖先),不然会WA。
2、在第二种处理方法中最后统计时比较的是find(i)和find(0)而不是pre[i]和pre[0]!
POJ 1611 The Suspects
题意:有n个学生,编号为0–n-1。有m个社团,每个社团有k位成员,接下来给出每位成员的编号,
如果一个社团里有一位成员感染了,那么这个社团的所有成员都被感染了。
已知编号为0的学生恒被感染。
问最终有多少位学生被感染了?
分析:
对于每一个社团成员除第一位成员外将所有成员都与第一位成员合并集合,最终只要查找和编号为0的学生公共祖先一样的学生人数即可。
有两种方法:
①:设一个数组num[maxn],num[i]表示以i为公共祖先的元素个数,最后只需输出num[0]。
②:输入合并完后,逐一统计和编号为0的嘘声公共祖先一样的学生人数。
注意:
1、在mix函数(合并操作)中,对两个集合合并时,要注意谁是谁的祖先(小数字是大数字的祖先),不然会WA。
2、在第二种处理方法中最后统计时比较的是find(i)和find(0)而不是pre[i]和pre[0]!
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int maxn = 30010; int pre[maxn], num[maxn];//num[i]表示以i为公共祖先的集合元素个数 int n, m, k, t, st; /* int find(int x) { return pre[x] == x ? x : pre[x] = find(pre[x]); } */ int find(int x) { int r = x; while (pre[r] != r) r = pre[r]; int i = x, j; while (pre[i] != r) { j = pre[i]; pre[i] = r; i = j; } return r; } void mix(int x, int y) { int fx = find(x); int fy = find(y); if (fx != fy) { if (fy < fx) swap(fy, fx);//公共祖先是较小的那一个 pre[fy] = fx; num[fx] += num[fy]; } } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); #endif while (~scanf("%d%d", &n, &m)) { if (n == 0 && m == 0) break; for (int i = 0; i < n; i++) { pre[i] = i; num[i] = 1;//每个num都初始为1 } for (int i = 0; i < m; i++) { scanf("%d", &k); for (int j = 0; j < k; j++) { if (j == 0) scanf("%d", &st); else { scanf("%d", &t); mix(st, t); } } } int com = pre[0];//com也等于find(0),即find(0)==pre[0]; //920K 16MS //int com = find(0); //920K 32MS //printf("%d\n", com); int ans = 0; for (int i = 0; i < n; i++) if (find(i) == com) ans++;//if里不是pre[i]==com!WA的心累啊! //pre[i]只是这个点的前导点,尽管find里已经路径压缩了,但仍然有可能有的点还未来得及更新 printf("%d\n", ans); //printf("%d\n", num[0]); } return 0; }
相关文章推荐
- C Function
- Swift和Objective-C的联系
- 机器学习中的数据清洗与特征处理综述
- 最近流行的MVP模式
- iOS开发之蓝牙通信
- test lab ~ triangle test by using junit and coverage
- 【Spring】学习SpringAOP
- linux grep命令
- 关于arguments.callee.caller.arguments[0]获得event的一些问题<转>
- In the shell, what does “ 2>&1 ” mean?
- JSP IE异步提交设置断点,有时走,有时不走,ajax缓存问题
- jquery全选和反选
- ORA-00392ORA-00312日志正在清除故障
- Windows API
- 内存管理的原则
- hdu 2082 找单词
- 设计图片下载器的过程以及问题
- ps命令详解
- 交换机上传下载文件配置文件
- 自动换行的button