在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)的更多相关文章

  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,Splay)

    在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. Windows控制程序网站带宽及Qos(TOS或DSCP)

    [基于策略的 Qos]位置:gpedit.msc->本地计算机策略->用户配置->Windows 设置->基于策略的 Qos

  2. React等开发工具记录

    React Native :React 起源于 Facebook 的内部项目,结合了 Web 应用和 Native 应用的优势,可以使用 JavaScript 来开发 iOS 和 Android 原生 ...

  3. Python操作Saltstack

    1.代码 # -*- coding:utf-8 -*- import urllib.request import urllib.parse import json class saltAPI(): d ...

  4. [CF1007D]Ants[2-SAT+树剖+线段树优化建图]

    题意 我们用路径 \((u, v)\) 表示一棵树上从结点 \(u\) 到结点 \(v\) 的最短路径. 给定一棵由 \(n\) 个结点构成的树.你需要用 \(m\) 种不同的颜色为这棵树的树边染色, ...

  5. win7笔记本VirtualBox安装黑苹果MacOS 10.13

    环境 时间:2018.04.09,没有指明时间的教程都是耍流氓 笔记本:某州优雅A460P-i7G D2,4G内存,Intel Core i7-2670QM四核八线程(老笔记本勉强能用),ssd硬盘, ...

  6. 【拾遗】理解Javascript中的Arguments

    前言 最近在看JavaScript相关的知识点,看到了老外的一本Javascript For Web Developers,遇到了一个知识盲点,觉得老外写的很明白很透彻,记录下来加深印象,下面是我摘出 ...

  7. Linux 终端快捷键整理

    一.历史命令相关快捷键 快捷键 说明 ↑.↓ 显示历史命令 !! 执行上一个命令 !n 执行历史命令中第 n 条命令 !-n 执行历史命令中倒数第 n 条命令 二.移动相关快捷键 快捷键 说明 Ctr ...

  8. 全局最小割StoerWagner算法详解

    前言 StoerWagner算法是一个找出无向图全局最小割的算法,本文需要读者有一定的图论基础. 本文大部分内容与词汇来自参考文献(英文,需***),用兴趣的可以去读一下文献. 概念 无向图的割:有无 ...

  9. Team Work Ⅱ

    Regal-Lighting团队设计 分工思考 本次大作业我的分工定位是:Unit及子类,主要设计实现建筑类的功能. 首先王者光耀这款游戏所需要的建筑分为三类: 1.防御塔:有一定的血量,血量为0时破 ...

  10. OpenFlow PacketOut消息机制

    OpenFlow PacketOut消息机制 前言 由于最近实验的进行,遇到一个比较棘手的问题,就是利用控制器主动发送packet消息的问题,期间遇到一些问题,后来在RYU群中得到群友左木的帮助成功解 ...