洛谷P4234 最小差值生成树(LCT,生成树)
和魔法森林有点像,都是动态维护最小生成树(可参考一下Blog的LCT总结相关部分)
至于从小到大还是从大到小当然无所谓啦,我是从小到大排序,每次枚举边,还没连通就连,已连通就替换环上最小的一条边,可以保证最优。如果已经构成了生成树,就可以更新答案,因为当前枚举到的一定是生成树里最大的,所以直接用当前减去最小更新答案。
至于最小的怎样维护,其实根本不需要什么别的set什么的数据结构。只要标记一下在生成树中的边,再搞一个指针指向在树中最小的边就好啦。当最小的边也被替换,就把指针后移,直到再找到一个在树中的边为止。
吐槽:注意了,有自环!!!我本来该1A却调试了2h,本地拿管理员的标程自造数据(没造自环)对拍几十万组无问题?!
卡常的地方挺多的,在LCT中应该算挺快的吧(比下面Niko巨佬的LCT代码快了\(1 \over 3\)左右,但是Niko巨佬写了个rank1的代码?!仔细看了下,是优化的暴力?貌似会被卡成\(O(NM)\)?!强烈建议再加强数据。。。。。。
#include<cstdio>
#include<algorithm>
using namespace std;
#define R register int
#define I inline void
#define lc c[x][0]
#define rc c[x][1]
#define in(z) ini=&z;\
while(*++q<'-');\
*ini=*q&15;\
while(*++q>'-')*ini*=10,*ini+=*q&15//读入卡常
const int N=50001,M=200009,L=N+M;
int f[L],c[L][2],mn[L],ff[N];
unsigned short v[L];//short卡常
bool r[L],vis[M];
char str[M<<6];
struct EDGE{
int u,v,l;
inline bool operator<(EDGE x)const{
return l<x.l;
}
}e[M];
inline bool nroot(R x){return c[f[x]][0]==x||c[f[x]][1]==x;}
inline int get(R x,R y){return v[x]<v[y]?x:y;}
I pushup(R x){mn[x]=get(x,get(mn[lc],mn[rc]));}
I pushdown(R x){
if(r[x]){
R t=lc;
r[lc=rc]^=1;r[rc=t]^=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;
}
I link(R i){//卡常版写法
mroot(e[i].u);
f[f[e[i].u]=N+i]=e[i].v;
}
I cut(R x){//也是卡常版写法
access(e[x-N].u);splay(x);
lc=rc=f[lc]=f[rc]=0;
}
int getf(R x){//并查集卡常
if(x==ff[x])return x;
return ff[x]=getf(ff[x]);
}
int main(){
fread(str,1,sizeof(str),stdin);//fread卡常
R n,m,i,x,y,h,cnt,ans,*ini;
register char*q=str-1;
in(n);in(m);
for(i=0;i<=n;++i)
ff[i]=i,v[i]=-1;
//-1放在unsigned里等于是极大值,注意v[0]也改了
for(i=1;i<=m;++i){
in(e[i].u);in(e[i].v);in(e[i].l);
}
sort(e+1,e+m+1);
for(cnt=h=i=1;i<=m;++i){
v[i+N]=e[i].l;
if(getf(x=e[i].u)!=getf(y=e[i].v))
{
vis[i]=1,link(i),ff[ff[x]]=ff[y],++cnt;
if(cnt==n)ans=e[i].l-e[h].l;
//刚完全建好生成树要马上更新答案
}
else{
if(x==y)continue;
vis[i]=1;
mroot(x);
access(y);splay(y);
vis[mn[y]-N]=0;while(!vis[h])++h;//维护好最小边
cut(mn[y]);link(i);
if(cnt==n)ans=min(ans,e[i].l-e[h].l);
}
}
printf("%d\n",ans);
return 0;
}
洛谷P4234 最小差值生成树(LCT,生成树)的更多相关文章
- 洛谷P4234 最小差值生成树(lct动态维护最小生成树)
题目描述 给定一个标号为从 11 到 nn 的.有 mm 条边的无向图,求边权最大值与最小值的差值最小的生成树. 输入输出格式 输入格式: 第一行两个数 n, mn,m ,表示图的点和边的数量. ...
- 【刷题】洛谷 P4234 最小差值生成树
题目描述 给定一个标号为从 \(1\) 到 \(n\) 的.有 \(m\) 条边的无向图,求边权最大值与最小值的差值最小的生成树. 输入输出格式 输入格式: 第一行两个数 \(n, m\) ,表示图的 ...
- 洛谷 P4234 最小差值生成树(LCT)
题面 luogu 题解 LCT 动态树Link-cut tree(LCT)总结 考虑先按边权排序,从小到大加边 如果构成一颗树了,就更新答案 当加入一条边,会形成环. 贪心地想,我们要最大边权-最小边 ...
- [洛谷P4234] 最小差值生成树
题目类型:\(LCT\)动态维护最小生成树 传送门:>Here< 题意:求一棵生成树,其最大边权减最小边权最小 解题思路 和魔法森林非常像.先对所有边进行排序,每次加边的时候删除环上的最小 ...
- 洛谷.4234.最小差值生成树(LCT)
题目链接 先将边排序,这样就可以按从小到大的顺序维护生成树,枚举到一条未连通的边就连上,已连通则(用当前更大的)替换掉路径上最小的边,这样一定不会更差. 每次构成树时更新答案.答案就是当前边减去生成树 ...
- 洛谷4234最小差值生成树 (LCT维护生成树)
这也是一道LCT维护生成树的题. 那么我们还是按照套路,先对边进行排序,然后顺次加入. 不过和别的题有所不同的是: 在本题中,我们需要保证LCT中正好有\(n-1\)条边的时候,才能更新\(ans\) ...
- P4234 最小差值生成树
题目 P4234 最小差值生成树 做法 和这题解法差不多,稍微变了一点,还不懂就直接看代码吧 \(update(2019.2):\)还是具体说一下吧,排序,直接加入,到了成环情况下,显然我们要把此边代 ...
- P4234 最小差值生成树 LCT维护边权
\(\color{#0066ff}{ 题目描述 }\) 给定一个标号为从 \(1\) 到 \(n\) 的.有 \(m\) 条边的无向图,求边权最大值与最小值的差值最小的生成树. \(\color{#0 ...
- 洛谷U19464 山村游历(Wander)(LCT,Splay)
洛谷题目传送门 LCT维护子树信息常见套路详见我的总结 闲话 题目摘自WC模拟试题(by Philipsweng),原题目名Wander,"山村游历"是自己搞出来的中文名. 数据自 ...
随机推荐
- log下一次坑爹的疏忽
今天调试一段十几行的代码,也让我是一顿咒骂...就说说是怎么回事哈哈. 是这样的,这个页面foreach了一个个的div块,每个div里有个a标签,这个按钮绑定了个点击事件.事件走了个ajax,根据返 ...
- AbelSu区块链应用场景收集
1.基于智能合约的众筹 众筹项目的资金通常由一个中心化不可变更且开放的数据库来控制,这个数据库可以追踪所有出资人. 虽然如此,我们可以用一种去中心化的方式来实现,而且只要创建一个代币就可以追踪资金.一 ...
- 20155333 《网络对抗》Exp2 后门原理与实践
20155333 <网络对抗>Exp2 后门原理与实践 1.例举你能想到的一个后门进入到你系统中的可能方式? 下载的软件中捆绑有后门: 浏览的网页或其上的小广告: 有些网页会自动安装软件. ...
- 汇编 REPE/REPZ 指令,CMPSB指令
知识点: REPE/REPZ 指令 CMPSB 指令 一.CMPSB //cmp //sub //SCASB//scasw//scasd cmp byte ptr [edi],al //对标志位的 ...
- 【HNOI2016】网络
题面 题解 考虑整体二分. 定义整体二分函数solve(l, r, ql, qr)表示操作权值在\([l, r]\)中,对\([ql, qr]\)的询问进行二分. 这样的话check就会很简单,先按照 ...
- HTML-JS 循环 函数 递归
[循环结构的执行步骤] 1.声明循环变量 2.判断循环条件 3.执行循环体操作 4.更新循环变量 然后,循环执行2-4,直到条件不成立时,跳出循环. while循环()中的表达式,运算结果可以是各种类 ...
- VPS性能测试(3):磁盘IO读写速度、SSD硬盘速度测试
1.磁盘IO,即输入/输出(Input/Output),这是测试磁盘性能一个重要指标,一些便宜的VPS主机为了降低成本,以大量的低性能的硬盘来充当服务器,导致VPS主机因为IO差而拖了整个主机性能的后 ...
- python爬虫-使用cookie登录
前言: 什么是cookie? Cookie,指某些网站为了辨别用户身份.进行session跟踪而储存在用户本地终端上的数据(通常经过加密). 比如说有些网站需要登录后才能访问某个页面,在登录之前,你想 ...
- Vim操作指南
vim具有6种基本模式和5种派生模式. 基本模式 普通模式 插入模式 可视模式 选择模式 命令行模式 Ex模式 派生模式 操作符等待模式 插入普通模式 插入可视模式 插入选择模式 替换模式 1.移动光 ...
- BackBone及其实例探究
摘要 我们小组对MVC框架进行了学习.我的队友们已经在博客中对MVC的设计模式及优缺点进行了详细的探讨与分析,因此我的博客中只对MVC进行简单的介绍,而我将把重心放在Backbone MVC框架一 ...