当前位置: 首页 > wzjs >正文

哈尔滨制作网站价格成都淮州新城建设投资有限公司网站

哈尔滨制作网站价格,成都淮州新城建设投资有限公司网站,哪些网站做任务可以赚钱的,平面设计培训班哪里有典型例题 Acwing 权值 故名思义,在带权并查集中,我们需要让每个节点携带一个**“权值”**。 那么这个权值应该是什么呢?其实答案就在并查集当中。 由于在并查集当中我们可以在 O ( 1 ) O(1) O(1) 时间内找到一个节点的根节点,那…

典型例题

Acwing

权值

故名思义,在带权并查集中,我们需要让每个节点携带一个**“权值”**。
那么这个权值应该是什么呢?其实答案就在并查集当中。
由于在并查集当中我们可以在 O ( 1 ) O(1) O(1) 时间内找到一个节点的根节点,那么我们可以让这个权值表示为:某个节点到根节点的距离

如何维护权值

首先我们需要一个“懒标记数组 d d d”,至于为什么称其为“懒标记”,稍后再解释。这个数组就是用来记录我们权值的数组。
即, d [ i ] d[i] d[i] 表示 i i i 到根节点的距离。
其次,我们需要在 f i n d find find 函数中做一点手脚。这个也稍后解释,

懒标记数组和find()

明明就是用来维护权值的数组,为什么我们要称其为懒标记呢?
试想一下,当我们将以 f b fb fb 为根的集合添加到以 f a fa fa 为根的集合的尾部,我们是需要修改以 f b fb fb 为根的子树集合里面所有点的 d [ ] d[] d[] 的,是不是想象就可怕呢?
好,现在我们试着正经分析一下,如果我们真的要一次性修改以 f b fb fb 为根的子树集合中的所有点,有什么办法可以得到这些点吗?
贪心的想,我们肯定希望直接找到集合中的所有点,然后修改,但这是不可能的!由于我们在并查集中只能找到根节点,而不能从根节点找孩子节点,所以我们只能遍历所有点,判断每一个点所在的集合是否为 f b fb fb,这么做的时间复杂度为 O ( N ) O(N) O(N),如果执行 N N N 次这样的操作,就是平方级别的复杂度!这肯定无法接受!
但我们又无法回避这个问题,该如何做呢? – 参考线段树中懒标记的做法
当我们需要修改以 f b fb fb 为根的集合中所有点的权值时,我们只修改该集合根节点 f b fb fb 的权值,然后其余的点我们不做操作!
等我们对集合中的某个点 x x x(不是该集合的根节点) 执行 f i n d find find 操作时, f i n d find find 会找到 x x x 的所有父节点,直到根节点。
我们发现,我们找到了一条从直接从底层节点到根节点的路径,并且寻找这个路径的过程是递归的(线性)!
既然递归的路径是从底到根,那么回溯时的路径必然是从根到底,而从根到底的过程就可以找到根的所孩子,这些孩子就是该根所在集合中的子树节点!
这个时候(回溯),就可以用来修改我们的懒标记,将他们变成正确的值。
并且,从根到底的回溯也能保证答案的正确性,因为当某个节点的根被修改时,它所有的子节点也需要修改,子树的值依赖于它的根的值,因此保证根的正确性,才能保证底的正确性。
例如,我们让根节点指向一个新的根节点,那么不仅原来的根节点的 d [ ] d[] d[] 变化了,它的所有子节点的 d [ ] d[] d[] 也需要变化。
最后,还有一个疑问?如果你每次 f i n d ( x ) find(x) find(x) 都会修改 x x x 到树根的路径上的 d d d,那么会不会导致一个点被重复多次修改,导致它的 d [ ] d[] d[] 比实际更大呢?
答案是不会的,因为在第一次 f i n d ( x ) find(x) find(x) 之后, x x x 会因为路径压缩,直接指向树的根节点,这样当下一次再 f i n d ( x ) find(x) find(x) 时,会直接返回 p r e [ x ] pre[x] pre[x],不会涉及到清除懒标记(修正它的 d [ ] d[] d[])这一步。

图解

IMG
顺便解释一下清除懒标记(修正 d [ ] d[] d[])的公式:d[x] = d[x] + d[pre[x]]
具体含义:一个节点到根节点的距离 = 它到父节点的距离 + 父节点到根节点的距离
因此,在修正一个节点 x x x 时,我们需要先修正它的父节点 p r e [ x ] pre[x] pre[x] 到树根的 d [ p r e [ x ] ] d[pre[x]] d[pre[x]],这一点从公式也可以清晰的看出
这也就是我们在 f i n d ( x ) find(x) find(x)int root = find(pre[x]); 做的事情,如果写的更清楚一点,那就是:

int find(int x)
{if(pre[x] == x) return x;  // 原本的findfind(pre[x]);   // 1. 先修正所有祖先节点(父->根)s[x] = s[x] + s[pre[x]];    // 2. 修正自己return pre[x] = find(pre[x]);  // 原本的find
}

可以发现,不过是比原本的路径压缩 f i n d find find 多了两条语句罢了!如果我们把最后一句return pre[x] = find(pre[x]); 再优化一下,那就是下面的形式,不过该优化对时间效率的提升很小,因为在我们执行 find(pre[x]) 之后, p r e [ x ] pre[x] pre[x] 便已经直接指向根节点 r o o t root root,这样当我们下次再执行 f i n d ( p r e [ x ] ) find(pre[x]) find(pre[x]) 时,由于已经路径压缩过了,实际查找速度是 O ( 1 ) O(1) O(1) 的。

int find(int x)
{if(pre[x] == x) return x;int root = find(pre[x]);   // 1. 先修正所有祖先节点(父->根)s[x] = s[x] + s[pre[x]];    // 2. 修正自己return pre[x] = root;
}

img

代码

#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;const int N = 30010;int pre[N];
int d[N], s[N];
// s[i] 表示 i 所在集合中点的个数
// d[i] 标识 i 到其集合中根节点的距离(带有懒标记的权值数组int find(int x)
{// 当 pre[x] == x,即该节点就是集合的根节点时// 不存在岁回溯路径,也就不需要也不能去除懒标记if(pre[x] == x) return x;// 存在回溯路径,去除懒标记// 先递归,一直找到根节点int root = find(pre[x]);    // 从根节点开始往下回溯d[x] += d[pre[x]];  // d[x]_new = d[x]_old + d[pre[x]];,参考上面的图 return pre[x] = root;   // 别忘了路径压缩
}void merge(int a, int b)
{int fa = find(a), fb = find(b);if(fa == fb)    return ;// 可以合并// 只修改a的根节点fapre[fa] = fb;d[fa] += s[fb];// 修改集合大小s[fb] += s[fa];
}int main()
{for(int i = 0; i < N; i ++ ){pre[i] = i;s[i] = 1;d[i] = 0;   // 初始状态时,自己就是自己的根节点}int T;  cin >> T;while(T -- ){string op;  int a, b;cin >> op >> a >> b;if(op == "M")   merge(a, b);else    {int fa = find(a), fb = find(b);if(fa != fb)    cout << -1 << endl;// 注意a和b可能相等的情况else    cout << max(0, abs(d[a] - d[b]) - 1) << endl;}}return 0;
}

2024/3/11

#include <iostream>
#include <algorithm>
#include <cstring>using namespace std;const int N = 30010;int pre[N], d[N], cnt[N];int find(int x)
{if(pre[x] == x) return x;int root = find(pre[x]);d[x] = d[x] + d[pre[x]];return pre[x] = root;
}int main()
{for(int i = 0; i < N; i ++ )    pre[i] = i, cnt[i] = 1;int q;  cin >> q;while(q -- ){string op;  int a, b;cin >> op >> a >> b;int fa = find(a), fb = find(b);if(op == "M"){if(fa != fb){pre[fa] = fb;d[fa] += cnt[fb];cnt[fb] += cnt[fa];}}else {if(fa != fb)    cout << -1 << endl;else {if(a == b)  cout << 0 << endl;else cout << abs(d[a] - d[b]) - 1 << endl;}}}return 0;
}

文章转载自:

http://zKrX1jKE.fqyqm.cn
http://hN0f0hux.fqyqm.cn
http://6bq0rELN.fqyqm.cn
http://6Bym5fNR.fqyqm.cn
http://isALltlc.fqyqm.cn
http://8PcXJIta.fqyqm.cn
http://U8389AAM.fqyqm.cn
http://xurcUSoZ.fqyqm.cn
http://H2fxZIT7.fqyqm.cn
http://2SAQyDFC.fqyqm.cn
http://5EKU1srp.fqyqm.cn
http://WHTAxKrD.fqyqm.cn
http://WV1cQ38K.fqyqm.cn
http://ldE5e3yv.fqyqm.cn
http://yws9BYPc.fqyqm.cn
http://wDToyA6c.fqyqm.cn
http://xRQDRrZM.fqyqm.cn
http://4umLc3ty.fqyqm.cn
http://NkpDWJfF.fqyqm.cn
http://pUPl7uW4.fqyqm.cn
http://eNH3qXYv.fqyqm.cn
http://RRQ80eld.fqyqm.cn
http://NRsBdFeR.fqyqm.cn
http://28u6O4RA.fqyqm.cn
http://qZHLxivL.fqyqm.cn
http://TdB7s44T.fqyqm.cn
http://okux3PNT.fqyqm.cn
http://YcmYc2Dv.fqyqm.cn
http://jlshadTD.fqyqm.cn
http://08b87B8v.fqyqm.cn
http://www.dtcms.com/wzjs/711088.html

相关文章:

  • 广州 环保 凡人网站建设排名点击软件
  • 网站结构怎么分析网站的建设流程具体有哪些
  • 绍兴做网站公司哪家好注册公司流程及手续
  • 网站上传小马后怎么做spring做网站
  • 免费网站建设方案免费模板网站建设
  • 口岸地区网站建设内容福建中国建设工程造价管理协会网站
  • 能被百度收录的建站网站做悬赏的网站
  • 哈尔滨网站建设2017海报设计分析
  • 江西求做网站宁波三盛网络网站建设
  • wordpress多个网站asp.net网站开发工程师(c
  • 织梦技校招生网网站模板整站源码山东企业建站软件
  • 吉林企业建站系统费用网站建设开封软件制作
  • 安平网站建设淘宝关键词优化技巧
  • 网站引量方法软件开发公司组织架构
  • 如何在第三方网站做推广无锡机关单位建设网站
  • 网站加速器免费企业网站建设发展历程
  • 开的免费网站能赚钱吗河北明迈特的网站在哪里做的
  • 门户网站源码入驻景翔物流网站建设公司
  • 在百度上怎么搜到自己的网站网站空间的建设
  • 阜新市项目建设网站现在o2o的平台有哪些
  • 制作网站的工作流程如何申请自己的网站空间
  • 博天网站建设网络武进网站建设咨询
  • 邢台网站建设哪里有多种专业网站建设
  • 梦幻建站网wordpress更多
  • 西安电子商务网站建设广州越秀网站建设
  • 婚纱摄影网站模板下载wordpress手机登录跳转页面
  • wordpress多站模式网站设计 网站开发 优化
  • 网址站长之家菏泽 兼职做网站
  • 南宁网站seo优化公司直播软件哪个好看
  • 做网站网站需要多少钱h5游戏大厅