【Luogu】P4234最小差值生成树(LCT)
能把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)的更多相关文章
- P4234 最小差值生成树 LCT维护边权
\(\color{#0066ff}{ 题目描述 }\) 给定一个标号为从 \(1\) 到 \(n\) 的.有 \(m\) 条边的无向图,求边权最大值与最小值的差值最小的生成树. \(\color{#0 ...
- Luogu P4234 最小差值生成树
题意 给定一个 \(n\) 个点 \(m\) 条边的有权无向图,求出原图的一棵生成树使得该树上最大边权与最小边权的差值最小. \(\texttt{Data Range:}1\leq n\leq 5\t ...
- 洛谷 P4234 最小差值生成树(LCT)
题面 luogu 题解 LCT 动态树Link-cut tree(LCT)总结 考虑先按边权排序,从小到大加边 如果构成一颗树了,就更新答案 当加入一条边,会形成环. 贪心地想,我们要最大边权-最小边 ...
- Luogu 4234 最小差值生成树 - LCT 维护链信息
Solution 将边从小到大排序, 添新边$(u, v)$时 若$u,v$不连通则直接添, 若连通则 把链上最小的边去掉 再添边. 若已经加入了 $N - 1$条边则更新答案. Code #incl ...
- luogu 4234 最小差值生成树 LCT
感觉码力严重下降~ #include <bits/stdc++.h> #define N 400006 #define inf 1000000000 #define setIO(s) fr ...
- P4234 最小差值生成树
题目 P4234 最小差值生成树 做法 和这题解法差不多,稍微变了一点,还不懂就直接看代码吧 \(update(2019.2):\)还是具体说一下吧,排序,直接加入,到了成环情况下,显然我们要把此边代 ...
- 洛谷.4234.最小差值生成树(LCT)
题目链接 先将边排序,这样就可以按从小到大的顺序维护生成树,枚举到一条未连通的边就连上,已连通则(用当前更大的)替换掉路径上最小的边,这样一定不会更差. 每次构成树时更新答案.答案就是当前边减去生成树 ...
- 洛谷P4234 最小差值生成树(lct动态维护最小生成树)
题目描述 给定一个标号为从 11 到 nn 的.有 mm 条边的无向图,求边权最大值与最小值的差值最小的生成树. 输入输出格式 输入格式: 第一行两个数 n, mn,m ,表示图的点和边的数量. ...
- 洛谷P4234 最小差值生成树(LCT,生成树)
洛谷题目传送门 和魔法森林有点像,都是动态维护最小生成树(可参考一下Blog的LCT总结相关部分) 至于从小到大还是从大到小当然无所谓啦,我是从小到大排序,每次枚举边,还没连通就连,已连通就替换环上最 ...
随机推荐
- python爬虫之路——初识爬虫三大库,requests,lxml,beautiful.
三大库:requests,lxml,beautifulSoup. Request库作用:请求网站获取网页数据. get()的基本使用方法 #导入库 import requests #向网站发送请求,获 ...
- HDU 5451 Best Solver(fibonacci)
感谢这道题让我复习了一遍线代,还学习了一些奇奇怪怪的数论. 令 二项展开以后根号部分抵消了 显然有 所以要求的答案是 如果n比较小的话,可以直接对二项式快速幂,但是这题n很大 这个问题和矩阵的特征值以 ...
- [dp uestc oj] G - 邱老师玩游戏
G - 邱老师玩游戏 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submi ...
- ECshop安装提示cls_image::gd_version() 和不支持JPEG
ecshop版本:ECShop_V2.7.3_UTF8_release1106php 版本 5.5--------------------------------------------------- ...
- nginx 的反向代理及缓存功能
上游服务器的设置 server { #监听的IP及端口 listen 127.0.0.1:8080; #虚拟主机对硬解析的主机名 #server_name localhost; #charset ko ...
- HTML之基本语法(链接标签、路径的介绍和使用)
一.链接标签 语法:<a href="目标地址">这个标签上展示的内容</a> 作用:可以实现在当前页面跳转到新页面的操作 属性 1.target这个属性可 ...
- python之函数默认参数的坑
坑 当你的默认参数如果是可变的数据类型,你要小心了 例题 # 正常没毛病的操作 def func(a,b=False): print(a) print(b) func(1,True) # 在实参角度, ...
- orcle定时备份
orcle定时备份 (1)写个.bat文件 例如: exp test/test@ORCL file=f:\back\test%date:~,%%date:~,%%date:~,%.dmp (2)开始, ...
- Bootstrap 下拉菜单(dropdown)插件
使用下拉菜单的插件,您可以向任何组件(比如:导航栏,标签页,胶囊式导航,按钮)添加下拉菜单 用法 您可以切换下拉菜单(dropdown)插件隐藏内容 1.通过data属性,向链接或按钮添加data-t ...
- 01_10_SERVLET如何连接Mysql数据库
01_10_SERVLET如何连接Mysql数据库 1. 实现类 public void doGet(HttpServletRequest request, HttpServletResponse r ...