题目链接

  能把LCT打得每个函数都恰有一个错误也是挺令我惊讶的。

  本题使用LCT维护生成树,具体做法是对原图中的每个边建一个点,然后连边的时候相当于是将边的起点跟“边”这个点连起来,边的终点也跟它连起来。

  放个图。

  

  比如这是原边。

  然后我们搞成这样。

  

  那个小点就是原来那条边啦。

  然后我们要连边的时候就连成这样

  

  比如小点的编号为new,我们就要link(from,new),link(to,new)

  切掉的时候就cut(from,new)cut(to,new)。

  之后呢,我们令splay的每个节点维护以自己为根的splay中连的权值最小的边是哪条,这样连成一个环的时候我们就可以很方便的把环中最小的那个边切掉,就可以维护啦

  

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cctype>
#include<queue>
#define maxn 500000
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} struct Edge{
int from,to,val;
bool operator <(const Edge a){
return val<a.val;
}
}edge[maxn]; bool cmp(Edge a,Edge b){ return a.val<b.val; }
int stack[maxn],top; struct Splay{
struct Node{
int e[],fa,val,mini,tag,id;
}tree[maxn];
inline int iden(int x){ return x==tree[tree[x].fa].e[]; }
inline bool isroot(int x){ return x!=tree[tree[x].fa].e[]&&x!=tree[tree[x].fa].e[]; }
inline void update(int x){
tree[x].mini=tree[x].id;
if(edge[tree[tree[x].e[]].mini].val<edge[tree[x].mini].val) tree[x].mini=tree[tree[x].e[]].mini;
if(edge[tree[tree[x].e[]].mini].val<edge[tree[x].mini].val) tree[x].mini=tree[tree[x].e[]].mini;
}
inline void connect(int x,int fa,int how){ tree[x].fa=fa; tree[fa].e[how]=x; }
inline void reverse(int x){
swap(tree[x].e[],tree[x].e[]);
tree[x].tag^=;
}
inline void pushdown(int x){
if(tree[x].tag==) return;
if(tree[x].e[]) reverse(tree[x].e[]);
if(tree[x].e[]) reverse(tree[x].e[]);
tree[x].tag=;
}
void rotate(int x){
int y=tree[x].fa,r=tree[y].fa;
int sony=iden(x),sonr=iden(y);
tree[x].fa=r; if(!isroot(y)) tree[r].e[sonr]=x;
int b=tree[x].e[sony^];
connect(b,y,sony);
connect(y,x,sony^);
update(y);
}
inline void pushto(int x){
top=;
while(!isroot(x)){
stack[++top]=x;
x=tree[x].fa;
}
pushdown(x);
while(top){
int from=stack[top--];
pushdown(from);
}
}
inline void splay(int x){
pushto(x);
while(!isroot(x)){
if(!isroot(tree[x].fa))
if(iden(x)==iden(tree[x].fa)) rotate(tree[x].fa);
else rotate(x);
rotate(x);
}
update(x);
}
void access(int x){
int last=;
while(x){
splay(x);
tree[x].e[]=last;
update(x);
last=x; x=tree[x].fa;
}
return;
}
inline void makeroot(int x){
access(x);
splay(x);
reverse(x);
}
inline void split(int x,int y){
makeroot(x);
access(y);
splay(y);
}
inline void link(int x,int y){
split(x,y);
tree[x].fa=y;
}
inline void cut(int x,int y){
split(x,y);
if(tree[y].e[]!=x||tree[x].e[]) return;
tree[x].fa=tree[y].e[]=;
}
inline int findroot(int x){
access(x);
splay(x);
while(tree[x].e[]) x=tree[x].e[];
return x;
}
}s; bool vis[maxn]; int main(){
int n=read(),m=read();
for(int i=;i<=m;++i) edge[i]=(Edge){read(),read(),read()};
sort(edge+,edge+m+,cmp); edge[].val=0x7fffffff;
for(int i=;i<=m;++i){
s.tree[i+n].val=edge[i].val;
s.tree[i+n].id=i;
}
int cnt=,now=;
int ans=0x7fffffff;
for(int i=;i<=m;++i){
int from=edge[i].from,to=edge[i].to,val=edge[i].val;
if(from==to){
vis[i]=;
continue;
}
//printf("D");
if(s.findroot(from)==s.findroot(to)){
s.split(from,to);
int mini=s.tree[to].mini;
//printf("%d>>>>\n",mini);
s.cut(edge[mini].from,mini+n);
s.cut(edge[mini].to,mini+n);
vis[mini]=;
cnt--;
} s.link(from,i+n); s.link(to,i+n);
cnt++;
if(cnt>=n-){
while(vis[now]) now++;//printf("S");
ans=min(ans,val-edge[now].val);
} }
printf("%d\n",ans);
return ;
}

【Luogu】P4234最小差值生成树(LCT)的更多相关文章

  1. P4234 最小差值生成树 LCT维护边权

    \(\color{#0066ff}{ 题目描述 }\) 给定一个标号为从 \(1\) 到 \(n\) 的.有 \(m\) 条边的无向图,求边权最大值与最小值的差值最小的生成树. \(\color{#0 ...

  2. Luogu P4234 最小差值生成树

    题意 给定一个 \(n\) 个点 \(m\) 条边的有权无向图,求出原图的一棵生成树使得该树上最大边权与最小边权的差值最小. \(\texttt{Data Range:}1\leq n\leq 5\t ...

  3. 洛谷 P4234 最小差值生成树(LCT)

    题面 luogu 题解 LCT 动态树Link-cut tree(LCT)总结 考虑先按边权排序,从小到大加边 如果构成一颗树了,就更新答案 当加入一条边,会形成环. 贪心地想,我们要最大边权-最小边 ...

  4. Luogu 4234 最小差值生成树 - LCT 维护链信息

    Solution 将边从小到大排序, 添新边$(u, v)$时 若$u,v$不连通则直接添, 若连通则 把链上最小的边去掉 再添边. 若已经加入了 $N - 1$条边则更新答案. Code #incl ...

  5. luogu 4234 最小差值生成树 LCT

    感觉码力严重下降~ #include <bits/stdc++.h> #define N 400006 #define inf 1000000000 #define setIO(s) fr ...

  6. P4234 最小差值生成树

    题目 P4234 最小差值生成树 做法 和这题解法差不多,稍微变了一点,还不懂就直接看代码吧 \(update(2019.2):\)还是具体说一下吧,排序,直接加入,到了成环情况下,显然我们要把此边代 ...

  7. 洛谷.4234.最小差值生成树(LCT)

    题目链接 先将边排序,这样就可以按从小到大的顺序维护生成树,枚举到一条未连通的边就连上,已连通则(用当前更大的)替换掉路径上最小的边,这样一定不会更差. 每次构成树时更新答案.答案就是当前边减去生成树 ...

  8. 洛谷P4234 最小差值生成树(lct动态维护最小生成树)

    题目描述 给定一个标号为从 11 到 nn 的.有 mm 条边的无向图,求边权最大值与最小值的差值最小的生成树. 输入输出格式 输入格式:   第一行两个数 n, mn,m ,表示图的点和边的数量. ...

  9. 洛谷P4234 最小差值生成树(LCT,生成树)

    洛谷题目传送门 和魔法森林有点像,都是动态维护最小生成树(可参考一下Blog的LCT总结相关部分) 至于从小到大还是从大到小当然无所谓啦,我是从小到大排序,每次枚举边,还没连通就连,已连通就替换环上最 ...

随机推荐

  1. Linux下解压ZIP压缩包乱码问题

    并不是所有ZIP文件都是乱码的而且导致解压失败,只有windows下压缩的ZIP在Linux中会出现这种情况.这是因为Windows和Linux下用的字符编码不同.Windows下的编码格式为GBK, ...

  2. Ubuntu下安装XAMPP

    来源:http://www.ido321.com/1265.html 最近,我也玩起了Linux了,瞬间觉得自己逼格又上去了,所以,就给笔记本安装了Ubuntu+Win7双系统.当然在Ubuntu下必 ...

  3. Android(java)学习笔记127:生成 4种不同权限的文件

    1. 首先我们编写一个生成 4种 不同权限的文件的程序案例: (1)首先是activity_main.xml文件: <RelativeLayout xmlns:android="htt ...

  4. appium---AndroidSdk安装

    AndroidSDK指的是Android专属的软件开发工具包,被软件开发工程师用于为特定的软件包.软件框架.硬件平台.操作系统等建立应用软件的开发工具的集合.Android又是采用java语言进行开发 ...

  5. Win10激活方法(企业版)

    Win10激活 注意:以管理员身份运行,需要电脑有网(亲测激活企业版没问题) 然后一条一条复制执行 slmgr /ipk NPPR9-FWDCX-D2C8J-H872K-2YT43 slmgr /sk ...

  6. CentOS 7.4 基于LNMP搭建wordpress

    之前有好多次搭建wordpress的经历,有在Ubuntu系统上,有在CentOS7.2系统上,但都是搭完还是稀里糊涂的,因为好多都是教程上照着敲的.这次好好出个教程,以便以后方便查看. 准备工作:C ...

  7. vue 项目白屏解决方案

    在做的项目是使用 vue-cli 脚手架为基础的,只能使用微信浏览器打开的.在某次更新功能代码后,被反馈在一些手机上会出现白屏.经过一番探索,多管齐下解决了问题 白屏可能的原因: es6 代码没有被编 ...

  8. python爬虫基础09-selenium大全3/8-Remote Webdriver

    Selenium笔记(3)Remote Webdriver 本文集链接:https://www.jianshu.com/nb/25338984 简介 selenium.webdriver.remote ...

  9. Restful API 概念解析

    什么是restful? REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”或“表现层状态转化”. ...

  10. leetcode-15-basic-string

    58. Length of Last Word 解题思路: 从结尾向前搜索,空格之前的就是最后一个词了.写的时候我考虑了尾部有空格的情况.需要注意的是,测试用例中有" "的情况,此 ...