HDU 3038 带权并查集裸题
来源:互联网 发布:seo app 编辑:程序博客网 时间:2024/05/19 04:29
花了好长时间才明白这个到底是怎么回事。
权值其实就是各个子节点与父节点的相对距离。
带权就是表示连接到父亲节点的子节点的那条边是有权值的,我们用另外一个数组来记录这个权值(或者你用结构体也行)。
个人习惯用w数组记录相对距离值,比如,w[2]=3表示序号为2的节点到其父亲的相对距离是3.
并查集这个pre数组中有很多颗树,每棵树都有自己的根节点,这一点和原先的不带权值的并查集没有区别。
有区别的是我们要记录子节点到父亲节点的相对距离。
我们所要维护的不止是树这个结构还要维护到根的距离这个东西。
带权并查集和不带权并查集的小比较
举个例子:
一、a、b、c在同一棵树上,a是根,b、c都是叶子;d、e、f在同一树上,d是根,e、f是叶子,没有附加的东西了,这个叫没权值的并查集,假设我要把c和e关联在一起,我只需要把他们弄到同一棵树上就可以了,不需要考虑他们到父节点点的相对距离。
二、a、b、c在同一棵树上,a是根,b、c都是叶子,b到a的相对距离是11,c到a的相对距离是12;d、e、f在同一树上,d是根,e、f是叶子,e到d的相对距离是13,f到d的相对距离是14。现在关联c和e:e比c远A。这样两棵树就因为这个关系要合并成一棵树了,用朴素的合并方法,只要把a节点(c的根节点)和d节点(e的根节点)连接起来,以d作为整棵树的根节点,然后通过换算(到底怎么算?下文有。)更新a到d的相对距离,这样就可以完成合并了。
正文:
一、各种操作:
1.找根节点,顺带路径压缩,体现在Find函数中。
2.合并两棵树,体现在unite函数中。
3.初始化。
这三个操作都是必要的。
二、Find函数:
路径压缩的引导就不必要了,直接说方法就可以。
因为要维护一个相对距离,我们让各个子节点认祖宗为父亲节点时,要把沿途子节点的所有父节点的权值都加上。
代码实现起来还是用了递归:
int Find(int x){ if(x==pre[x]) return pre[x]; int t=Find(pre[x]); w[x]+=w[pre[x]]; return pre[x]=t;}
除去第三行,你会发现和原先不带权的并查集的Find函数一样,这里只不过是把沿途的父节点的权值都加上了而已。
三、unite函数:
还是传统的联结两棵树的根节点
void unite(int a,int b,int weight){ int fa=Find(a); int fb=Find(b); if(fa!=fb) { pre[fb]=fa; w[fb]=w[a]-w[b]+weight; }}
这里要提醒一点,这个保证给出的联结条件是正确的,有些题目是需要判断这些联结条件是否正确。
那么上文提到了“通过某种换算”可以算出两个根节点的相对距离,到底怎么算?
举个例子:
还是上文提到的,最好自己手动画两棵树哦~
a、b、c在同一棵树上,a是根,b、c都是叶子,b到a的相对距离是11,c到a的相对距离是12;d、e、f在同一树上,d是根,e、f是叶子,e到d的相对距离是13,f到d的相对距离是14。现在关联c和e:e比c的远10(e-c=10)(注意这里不能简单说e与c的距离是10,这样给的信息只有相对距离而没有说谁离根更远),这对应于代码中就是参数为(c,e,10)参数用数字表示了节点序号,我用了字母表示了节点序号。
假设参数b离根节点更远,我们采用的是左归并,即右面的树归并到左边的树上。
e-c=10,对应于参数来说就是(c,e,10)注意参数是要有严格的远近顺序的。
还是经典的合并,我想要a对d的相对距离,也就是a比d远多少。
我们已经知道c比a远12(w[c])了,e比c远10(weight),那么e比a远10+12(weight+w[c]),我们本身知道了e比d远13(w[e])
那么我们想求的a比d远的值就是e比a远的减去e比d远的(weight+w[c]-w[e])。
或者你也可以解方程组,也挺简单的。
对应到代码上,就是
也就是weight+w[a]-w[b];
以后更新,还有些问题……
- HDU 3038 带权并查集裸题
- hdu 3038带权并查集
- hdu-3038 带权并查集
- hdu 3038 带权并查集
- hdu 3038 带权并查集
- HDU 3038 带权并查集
- hdu 3038(带权并查集)
- HDU 3038 带权并查集判错(详解)
- HDU 3038 带权并查集,区间
- hdu 2818 带权并查集
- hdu 3047 带权并查集
- hdu 3635 带权并查集
- HDU 3635 带权并查集
- HDU 3047 带权并查集
- HDU 3074 带权并查集
- HDU 3047 带权并查集
- hdu 3047 带权并查集
- hdu 3047 (带权并查集)@
- @SuppressWarnings注解
- CodeChef
- 线段树基本
- 求最长子序列模板
- HNUSTOJ 1601:名字缩写
- HDU 3038 带权并查集裸题
- 动态规划快速入门 之 经典的数塔问题
- linux 命令提示符环境变量设置
- {模板}ZKW线段树
- 命名空间namespace的作用
- python关于文件的常用操作
- struts2简单入门-登陆示例
- QT+MSVC2010+Win7轻量级32位开发环境搭建
- Java是什么