
ACM-ICPC寒假算法训练2:高级数据结构1(并查集):基础并查集
发布日期:2021-05-07 02:18:43
浏览次数:29
分类:精选文章
本文共 2226 字,大约阅读时间需要 7 分钟。
并查集训练1:基础并查集
题1:
算法分析:
这题就是数朋友圈的数目,可以用并查集或者DFS,说明并查集可以用于计算联通块的数目。只需要把是朋友的并在一起,选取一个作为代表,然后去数有多少个代表就是有多少个圈子。
Solving code:
#define _CRT_SECURE_NO_WARNINGS#includeconst int maxn = 1005;int t, n, m, p[maxn];int find(int x) { if (x == p[x]) return x; return p[x] = find(p[x]);}void merge(int x, int y) { int px = find(x), py = find(y); if (px != py) p[py] = px;}int main() { scanf("%d", &t); while (t--) { scanf("%d %d", & n, &m); for (int i = 1; i <= n; i++) p[i] = i; int ans = 0; for (int i = 0; i < m; i++) { int a, b; scanf("%d %d", &a, &b); merge(a, b); } for (int i = 1; i <= n; i++) { if (i == p[i]) ans++; } printf("%d\n", ans); } return 0;}
题二:
算法分析:
这题的算法和上一题是一样的,完全一样,就是同一信仰的人被合并到一起,去数有多少种信仰就可以了!
Solving code:
#define _CRT_SECURE_NO_WARNINGS#includeconst int maxn = 5e4 + 5;int kcase, n, m, p[maxn];int find(int x) { if (x == p[x]) return x; return p[x] = find(p[x]);}void merge(int x, int y) { int px = find(x), py = find(y); if (px != py) p[py] = px;}int main() { while (scanf("%d %d", &n, &m) && (n || m)) { kcase++; for (int i = 1; i <= n; i++) p[i] = i; int ans = 0; for (int i = 0; i < m; i++) { int a, b; scanf("%d %d", &a, &b); merge(a, b); } for (int i = 1; i <= n; i++) if (i == p[i]) ans++; printf("Case %d: %d\n", kcase, ans); } return 0;}
题三:
算法分析:
这题比前两天稍微有意思一点,但是也是简单题。我们设定编号为 0 的是嫌疑人,和 0 一组的都是嫌疑人,问有多少个嫌疑人。那样我们可以每组并在一起,以为我们并不一定是以0 为 0所在组的代表,所以我们做最后统计的时候,万万不可以:if(!p[i]) ans++;
这样是绝对错误的!因为我们的 0 可能最后的p[0] != 0,所以我们应该要去搜索 i 所在的组,是不是与 0 同组:if(find(i) == p[0]) ans++;
Solving code:
#define _CRT_SECURE_NO_WARNINGS#includeconst int maxn = 5e4 + 5;int n, m, p[maxn];int find(int x) { if (x == p[x]) return x; return p[x] = find(p[x]);}void merge(int x, int y) { int px = find(x), py = find(y); if (px != py) p[py] = px;}int main() { while (scanf("%d %d", &n, &m) && (n || m)) { for (int i = 0; i < n; i++) p[i] = i; int ans = 0; for (int i = 0; i < m; i++) { int k, a, b; scanf("%d", &k); if (k--) scanf("%d", &a); while (k--) { scanf("%d", &b); merge(a, b); } } for (int i = 0; i < n; i++) if (find(i) == p[0]) ans++; printf("%d\n", ans); } return 0;}
发表评论
最新留言
表示我来过!
[***.240.166.169]2025年04月07日 10时49分06秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
onFailure unexpected end of stream
2021-05-12
android 集成weex
2021-05-12
【echarts】中国地图china.js 在线引用地址
2021-05-12
Flex 布局的自适应子项内容过长导致其被撑大问题
2021-05-12
PL/SQL 动态Sql拼接where条件
2021-05-12
Lua-table 一种更少访问的安全取值方式
2021-05-12
虚函数
2021-05-12
菱形继承
2021-05-12
RTL设计- 多时钟域按顺序复位释放
2021-05-12
斐波那契数列两种算法的时间复杂度
2021-05-12
int main(int argc,char* argv[])详解
2021-05-12
【Android踩过的坑】7.Android Studio 点击启动项目时进入调试模式
2021-05-12
【Android小技巧】1.快速查看SDK对应的API Level
2021-05-12
【自学Flutter】4.1 Material Design字体图标的使用(icon)
2021-05-12
C++清空队列(queue)方法
2021-05-12
【换行符】什么时候用cin.get()吃掉输入流中的换行符
2021-05-12
【二叉树】已知后序与中序求先序
2021-05-12
数组范围的动态扩容
2021-05-12