在XZY&XZZ巨佬的引领下,一枚蒟蒻终于啃动了这道题。。。。。。

这次还是第一次写LCT维护边权,还要化边为点,思路乱七八糟的,写起来也不顺手,还好调了许久终于AC啦。

贪心排序按一个关键字从小到大枚举边,维护另一个关键字的最小生成树,这样的思路真是太巧妙啦。(然而没有题解的滋养我什么也干不了)

只是关于写法上面,我又有些和Dalao们不一样的地方(因为是自己乱写的)。

link和cut好像脱离了传统意义,本蒟蒻用了link(x)表示将编号为x的边加入用LCT维护的最小生成树,cut(x)反之。

link其实是要连两次,因为要严格深度递增,就让边的一个端点的父亲指向这个代表边的点(轻边),再让代表边的点的父亲指向边的另一个端点(还是轻边)。当然啦,深度大的那个点要先makeroot,不然会影响正确性。

cut就是断两次了,把代表边的点下面那个点(深度大的)access,splay(代表边的点),此时两个端点一个深度小,在左边,一个深度大,在右边,左右儿子全断掉就OK。

其实常规link,cut没问题啊,我也不知道什么时候脑袋短路搞出这种不成熟的写法,不过稍微算算,实际操作量少了些,比起两遍link或cut常数会小一点。

update:这种link和cut可能存在问题。。。还是要写两遍(不知道当时怎么过的)

不过说到常数又留下一个败笔——这一题较特殊,维护连通性可以用并查集,避免了大量findroot(虽然不会T而已)。只是我没有写。findroot真慢呀!以后还是要记住这个小细节。

代码还是放一下

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define R register int
#define I inline void
#define lc c[x][0]
#define rc c[x][1]
#define G ch=getchar()
#define min2(x,y) if(x>y)x=y;
const int N=200000,P=131072;
//P是用来区分点和边的,边的编号在LCT中不变,点的编号全部加上P(为压常用了这样一个数,加上位或运算)
int f[N],c[N][2],mx[N];
bool r[N];
I in(R&z){
register char G;
while(ch<'-')G;
z=ch&15;G;
while(ch>'-')z*=10,z+=ch&15,G;
}
struct EDGE{
int u,v,a,b;
inline bool operator<(EDGE x)const{
return a<x.a;
}
I read(){
in(u);in(v);in(a);in(b);
u|=P;v|=P;//编号变化
}
}e[N];//边放进结构体
inline bool nroot(R x){
return c[f[x]][0]==x||c[f[x]][1]==x;
}
I pushup(R x){
mx[x]=x;
if(e[mx[x]].b<e[mx[lc]].b)mx[x]=mx[lc];
if(e[mx[x]].b<e[mx[rc]].b)mx[x]=mx[rc];//三种情况都要看
}
I pushdown(R x){
if(r[x]){
R t=lc;lc=rc;rc=t;
r[lc]^=1;r[rc]^=1;r[x]=0;
}
}
I pushall(R x){//懒得手写栈,直接用函数堆栈(逃
if(nroot(x))pushall(f[x]);
pushdown(x);
}
I rotate(R x){
R y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
if(nroot(y))c[z][c[z][1]==y]=x;c[x][!k]=y;c[y][k]=w;
f[w]=y;f[y]=x;f[x]=z;
pushup(y);
}
I splay(R x){
R y=x;
pushall(x);
while(nroot(x)){
if(nroot(y=f[x]))
rotate((c[y][0]==x)^(c[f[y]][0]==y)?x:y);
rotate(x);
}
pushup(x);
}
I access(R x){
for(R y=0;x;x=f[y=x])
splay(x),rc=y,pushup(x);
}
I mroot(R x){
access(x);splay(x);
r[x]^=1;
}
inline int froot(R x){
access(x);splay(x);
while(lc)x=lc;
return x;
}
I link(R x){
R y=e[x].u,z=e[x].v;
mroot(z);
f[f[z]=x]=y;
}//非正常link与cut
I cut(R x){
access(e[x].v);splay(x);
lc=rc=f[lc]=f[rc]=0;
pushup(x);
}
int main(){
R n,m,i,y,z,ans=999999;//ans给极大值
in(n);in(m);
for(i=1;i<=m;++i)e[i].read();
sort(e+1,e+m+1);
for(i=1;i<=m;++i)
{
if((y=e[i].u)==(z=e[i].v))continue;
mroot(y);
if(y!=froot(z))link(i);//不联通,直接连
else if(e[i].b<e[mx[z]].b)cut(mx[z]),link(i);//联通,但有更小的边替换
mroot(1|P);
if((1|P)==froot(n|P))min2(ans,e[i].a+e[mx[n|P]].b);//1与n联通就更新答案
}
printf("%d\n",ans==999999?-1:ans);
return 0;
}

洛谷P2387 [NOI2014]魔法森林(LCT,Splay)的更多相关文章

  1. 洛谷P2387 [NOI2014]魔法森林(LCT)

    魔法森林 题目传送门 解题思路 把每条路按照\(a\)的值从小到大排序.然后用LCT按照b的值维护最小生成树,将边按照顺序放入.如果\(1\)到\(n\)有了一条路径,就更新最小答案.这个过程就相当于 ...

  2. 洛谷 P2387 [NOI2014]魔法森林 解题报告

    P2387 [NOI2014]魔法森林 题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2 ...

  3. 洛谷P2387 [NOI2014]魔法森林(lct维护最小生成树)

    题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...

  4. 洛谷P2387 [NOI2014]魔法森林(LCT)

    在XZY&XZZ巨佬的引领下,一枚蒟蒻终于啃动了这道题...... 这次还是第一次写LCT维护边权,还要化边为点,思路乱七八糟的,写起来也不顺手,还好调了许久终于AC啦. 贪心排序按一个关键字 ...

  5. 洛谷 2387 NOI2014魔法森林 LCT

    [题解] 我们先把边按照$a$值从小到大排序,并按照这个顺序加边. 如果当前要加入的边连接的两点$u$与$v$已经是连通的,那么直接加入这条边就会出现环.这时我们需要删除这个环中$b$值最大的边.因此 ...

  6. P2387 [NOI2014]魔法森林 LCT维护最小生成树

    \(\color{#0066ff}{ 题目描述 }\) 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 ...

  7. 洛谷2387 NOI2014魔法森林(LCT维护最小生成树)

    本题是运用LCT来维护一个最小生成树. 是一个经典的套路 题目中求的是一个\(max(a_i)+max(b_i)\)尽可能小的路径. 那么这种的一个套路就是,先按照一维来排序,然后用LCT维护另一维 ...

  8. [Luogu P2387] [NOI2014]魔法森林 (LCT维护边权)

    题面 传送门:https://www.luogu.org/problemnew/show/P2387 Solution 这题的思想挺好的. 对于这种最大值最小类的问题,很自然的可以想到二分答案.很不幸 ...

  9. 【洛谷P2387】魔法森林

    题目大意:给定一个 N 个点,M 条边的无向图,边有两个边权 a, b,求从 1 号节点到 N 号节点路径的两个权值和的最大值最小是多少. 题解: 对于有两个属性的结构的最优化问题,可以考虑先按照其中 ...

随机推荐

  1. 在CentOS 6.x上配合Windows客户端搭建 git(gitosis)服务器

    一.在 CentOS 上安装 git 和 gitosis: 逐条执行如下语句: sudo yum install git python-setuptools cd /opt sudo git clon ...

  2. python数据分析工具包(2)——Numpy(二)

    上一篇文章简单地介绍了numpy的一些基本数据类型,以及生成数组和矩阵的操作.下面我们来看一下矩阵的基本运算.在线性代数中,常见的矩阵运算包括,计算行列式.求逆矩阵.矩阵的秩等.下面我们来一一实现. ...

  3. 基于layui和bootstrap搭建极简后台管理框架

    年前无聊,想自己搭建一个后台管理框架,对比了easyui.Extjs.H-ui.H+UI.layui几个框架,easyui和Extjs虽然功能强大但是界面实在是接受不了,H+UI和layuiAdmin ...

  4. LNMP环境下搭建wordpress

    WordPress 下载WordPress安装包,可以直接wget获取也可以ftp上传,解压到/usr/share/nginx/html/blog-wp,访问index.php即进行安装:   wor ...

  5. Js常用的函数

    1.用于对正则表达式的函数: var pattern=/\d{3}-\d{2}-\d{4}/;//这里产生的是一个object类型 alert(pattern.test("cscscscs& ...

  6. Spring中的注解@Service @Component @Controller @Repository区别

    @Service用于标注业务层组件, @Controller用于标注控制层组件(如struts中的action), @Repository用于标注数据访问组件,即DAO组件, @Component泛指 ...

  7. Windows下nexus-3.*搭建Maven私服

    1.下载 从官网下载https://help.sonatype.com/display/NXRM3/Download 选择Windows archive https://download.sonaty ...

  8. CSS 圣杯布局升级版---多个固定宽度一个自适应宽度

    1.一个div固定,一个div自适应宽度.两种情况,固定在左或者在右. HTML: <div class="box1"> <div class="mai ...

  9. PHP - curl实现采集

    1.开启curl支持 由于php环境安装后默认是没有打开curl支持的,需修改php.ini文件,找到;extension=php_curl.dll,把前面的冒号去掉,重启服务即可: 2.使用curl ...

  10. Batch Normalization&Dropout浅析

    一. Batch Normalization 对于深度神经网络,训练起来有时很难拟合,可以使用更先进的优化算法,例如:SGD+momentum.RMSProp.Adam等算法.另一种策略则是高改变网络 ...