开始了新一轮的学习,内容有并查集:
1.浅学一下路经压缩:
如果元素很多并且形成一条链,时间复杂度会很高,优化后时间复杂度变为O(1)。
int findfather(int x){
int a=x;
while(x!=father[x]){
x=father[x];
}
while(a!=father[a]){
int z=a;
a=father[a];
father[z]=x;
}
return x;
}
2.尤其注意合并两个点时是合并的两个集合根结点。
看的题目:
Poj 2524 Ubiquitous Religions
https://blog.csdn.net/weixin_34268843/article/details/94508147
我一开始差点以为要用到搜索,心想之前学的终于能和新知识一起结合使用了,结果发现不是。
不需要搜索,当x,y两个人是朋友的时候,并到一个根结点下面,此根结点的价格取原先的father[x]和father[y]价格的最小值,最后只求和i=father[i]的价格。
P1396 营救
看了这个题我的本能想法还是搜索,忽略了可以巧妙的运用并查集简化问题。
我的做法:
把每条边存在结构体中,先按权值升序排列,从最小权值的边往图里加,加到两个终点联通的时候,输出这个权值。
P1455 搭配购买
先用并查集将每个联通的图和并成一个大云,因为其中的每个云都是要捆绑销售的,再用深搜的方法求得最大总价值
P1536 村村通
这个巨简单,小联通块的个数减1,就是答案
所以用并查集
P1656 炸铁路
枚举每一条边,假设将他去掉后随便选一个点进行搜索,如果不能到达所有边,代表这是key road。
2078 朋友
用并查集,男生以B为父亲结点,女生以A为父亲结点,求两人集合元素个数的最小值
这道题中STL的巧妙运用:
由于女生用负数编号,而数组下标是非负整数,所以我们可以用map映射来储存女生的编号到键中,储存父结点到值中。
P2661 信息传递
一开始错误理解题意了:
因为并查集产生的每一个集合都是一棵树,这个题也就是求一棵树的最长边
正确题意:
听到自己的信息就算结束,只有存在环时才能收回自己的信息,所以最小环的元素数量就是游戏轮数。
我认为最好的题解:
如果一个人的入度为0,则肯定不可能成环,那么把这个人和他连出的边删去(即标记这个人并将他下一个人的入度减 1),
如果下一个人的入度为0则将他也删去……最后把所有入度为0的人都删去了,剩下的都是环。
每个人的出度为1,所以每个人只能在一个环中,每条边只能在一个环中,也就是说每个环都是分开的,
然后进行一遍 dfs,找出最小的环。
刚开始学觉得并查集很简单都是些套公式的东西,但是做题后发现难点在于我看到一些难的题目能不能想到用并查集去解决这个问题,一些难题当我们巧妙运用并查集这个简单的算法工具就能迎刃而解。