洛谷 P3420 [POI2005]SKA-Piggy Banks 题解

蒟蒻的第二篇题解

嗯,直接进入正题

先告诉你们这是并查集,好吧,标签上面有,再来分析这为什么是并查集。

根据题意:

每一个存钱罐能够用相应的钥匙打开或者被砸开,Byteazar已经将钥匙放入到一些存钱罐中

我们可以理解成:

如果这是一个联通块的“祖先”(也可以称为根吧,蒟蒻不知道该怎么称呼)那么就把它砸破,这样整个联通块就都可以取出;

如果不是的话,就不管它;

从后面句话就可以很明显的推出他们之间有从属关系(如果要砸的数目最小),这是并查集的思想,是吧;

好,既然我们已经知道了它要用并查集做;

那么,就是一个模板呀,上模板就可以了,最后输出联通块的个数;

OK,上代码,代码中也有注释:

#include<bits/stdc++.h>
using namespace std; #define maxn 1000010 int n, ans, x, fa[maxn]; /* //三目运算符版本 int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x)' } */ //普通的呐 int find(int x) { if(fa[x] == x) return x; return fa[x] = find(fa[x]); } int main() { scanf("%d", &n); for(int i = 1; i <= n; ++ i) fa[i] = i;//最开始,每个人都是自己的祖先; for(int i = 1; i <= n; ++ i) { scanf("%d", &x); fa[find(i)] /*找祖先*/ = find(x)/*找它的儿子的祖先*/; //就是合并两个集合呐 } for(int i = 1; i <= n; ++ i) if(fa[i] == i)//求联通块的个数 ++ ans; printf("%d", ans); return 0; }

转载于:https://www.cnblogs.com/Flash-plus/p/11210685.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值