洛谷P4234 最小差值生成树 题解

题目链接:P4234 最小差值生成树

题意:给定一个点标号从 111 到 nnn 的、有 mmm 条边的无向图,求边权最大值与最小值的差值最小的生成树,图可能存在自环

这个题不太好利用kruskal来维护(其实kruskal来做就是暴力枚举)

考虑使用LCT动态维护生成树

可以先回顾一下如何用LCT来求解最小生成树 link

因为边之间没有什么本质区别,我们可以先把边按大小排序,以保证编号越小的边点,权值越小

然后我们可以从小到大枚举生成树中的最大值(从大到小其实是类似的)

那么我们只要保证生成树中边权的最小值尽可能的大即可

也就是说,在枚举最大边的时候,如果两结点未连通,我们可以直接将这两点连接

如果已经连通,那么就将当前生成树中x,y所成的链中的最小边扔掉,然后用最大边连接这两点

显然这个最小值就是生成树中编号最小的那一个,而且随着枚举会单调不降,那我们可以整个变量记录它,而由于它的单调不降性质,寻找这个最小值是不会影响到复杂度的

对于已经不在生成树的边(包括构成自环和被更新掉的边),我们直接让那个维护最小值的变量跳过它就行了,具体可以看下面代码

时间复杂度 O(mlog⁡m)O(m\log m)O(mlogm)

代码如下

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define gc() getchar()
#define pc(a) putchar(a)
#define N (int)(4e5+5)
template<typename T>void read(T &k)
{char ch=gc();T x=0,f=1;while(!isdigit(ch)){if(ch=='-')f=-1;ch=gc();}while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=gc();}k=x*f;
}
template<typename T>void write(T k)
{if(k<0){k=-k;pc('-');}if(k>9)write(k/10);pc(k%10+'0');
}
int n,m,idx,ans=INF,cnt,d;
namespace LCT
{struct Edge{int u,v,w;}e[N];int cmp(Edge a,Edge b){return a.w<b.w;}struct node{int ch[2],id,fa,tag,vis;}t[N];#define isroot(x) ((t[t[x].fa].ch[0]!=x)&&(t[t[x].fa].ch[1]!=x))void pushr(int x){swap(t[x].ch[0],t[x].ch[1]);t[x].tag^=1;}void push_up(int x){t[x].id=x;if(t[t[x].ch[0]].id>n&&(t[x].id<=n||t[x].id>t[t[x].ch[0]].id))t[x].id=t[t[x].ch[0]].id;if(t[t[x].ch[1]].id>n&&(t[x].id<=n||t[x].id>t[t[x].ch[1]].id))t[x].id=t[t[x].ch[1]].id;}void push_down(int x){if(t[x].tag){if(t[x].ch[0])pushr(t[x].ch[0]);if(t[x].ch[1])pushr(t[x].ch[1]);t[x].tag=0;}}void push_all(int x){if(!isroot(x))push_all(t[x].fa);push_down(x);}void rotate(int x){int y=t[x].fa;int z=t[y].fa;int k=t[y].ch[1]==x;if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;t[x].fa=z;t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].fa=y;t[x].ch[k^1]=y;t[y].fa=x;push_up(y);push_up(x);}void splay(int x){push_all(x);while(!isroot(x)){int y=t[x].fa;int z=t[y].fa;if(!isroot(y))(t[z].ch[1]==y)^(t[y].ch[1]==x)?rotate(x):rotate(y);rotate(x);}}void access(int x){for(int y=0;x;y=x,x=t[x].fa)splay(x),t[x].ch[1]=y,push_up(x);}void make_root(int x){access(x);splay(x);pushr(x);}int find_root(int x){access(x);splay(x);while(t[x].ch[0])push_down(x),x=t[x].ch[0];splay(x);return x;}void split(int x,int y){make_root(x);access(y);splay(y);}void link(int x,int y){make_root(x);if(find_root(y)!=x)t[x].fa=y;}/*void cut(int x,int y){make_root(x);if(find_root(y)==x&&t[y].fa==x&&!t[y].ch[0]){t[x].ch[1]=t[y].fa=0;push_up(x);}}*/int ck(int x,int y){make_root(x);return find_root(y)!=x;}
}
signed main()
{using namespace LCT;read(n);read(m);for(int i=1; i<=m; i++){read(e[i].u);read(e[i].v);read(e[i].w);}sort(e+1,e+1+m,cmp);d=1;for(int i=1; i<=m; i++){int idx=n+i,w=e[i].w,x=e[i].u,y=e[i].v;if(x==y){t[idx].vis=1;continue;}if(ck(x,y))link(x,idx),link(idx,y),++cnt;else{split(x,y);int now=t[y].id;t[now].vis=1;splay(now);t[t[now].ch[0]].fa=t[t[now].ch[1]].fa=0;link(x,idx);link(idx,y);}while(t[d+n].vis&&d<i)++d;if(cnt>=n-1)ans=min(ans,w-e[d].w);}write(ans);pc('\n');return 0;
}

顺便贴一下kruskal的暴力代码吧 时间复杂度是 O(m2)O(m^2)O(m2) 的

这道题数据水过头了所以暴力也能过(已经反馈了

注:这个暴力是我去年(2021.2.6)写的,所以码风区别较大((

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define R register
int n,m,t,head[50005],in[50005],ans=INT_MAX,pos=1,cnt;
int f[50005],a[50005];
struct Edge
{int u,v,w,next;const bool operator<(const Edge &o)const{return w<o.w;}
}e[500005];
void init()
{for(R int i=1; i<=n; i++)f[i]=i;cnt=0;
}
void add(R int u,R int v,R int w)
{e[pos]={u,v,w,head[u]};head[u]=pos++;
}
int find(R int x)
{return f[x]==x?x:f[x]=find(f[x]);
}
signed main()
{scanf("%lld%lld",&n,&m);for(R int i=1,u,v,w; i<=m; i++){scanf("%lld%lld%lld",&u,&v,&w);add(u,v,w);}if(m==0)return puts("-1"),0;sort(e+1,e+pos+1);for(R int k=1; k<=pos; k++){if(k>1&&e[k].w==e[k-1].w)continue;init();for(R int i=k;i<=pos; i++){R int u=find(e[i].u),v=find(e[i].v),w=e[i].w;if(u==v)continue;f[u]=v;if(++cnt==n-1){if(ans>e[i].w-e[k].w)ans=e[i].w-e[k].w;break;}}if(cnt!=n-1)break;}printf("%lld\n",ans);return 0;
}

转载请说明出处

洛谷P4234 最小差值生成树 题解相关推荐

  1. [洛谷P4234]最小差值生成树

    给定一个标号为从$1$到$n$的.有$m$条边的无向图,求边权最大值与最小值的差值最小的生成树. 做法类似魔法森林,首先求出来最小生成树,然后每次加入一条边,断掉环上最小边并更新答案 这个过程我用两个 ...

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

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

  3. 洛谷P5633 最小度限制生成树 题解

    洛谷P5633 最小度限制生成树 题解 题目链接:P5633 最小度限制生成树 题意: 给你一个有 n n n 个节点, m m m 条边的带权无向图,你需要求得一个生成树,使边权总和最小,且满足编号 ...

  4. 洛谷P2619 [国家集训队]Tree I 题解

    洛谷P2619 [国家集训队]Tree I 题解 题目链接:P2619 [国家集训队]Tree I 题意: 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有 need\text{n ...

  5. 洛谷P1282 多米诺骨牌 题解

    洛谷P1282 多米诺骨牌 题解 题目链接:P1282 多米诺骨牌 题意: 多米诺骨牌由上下 222 个方块组成,每个方块中有 1∼61\sim61∼6 个点.现有排成行的上方块中点数之和记为 S1S ...

  6. 洛谷P3237 [HNOI2014]米特运输 题解

    洛谷P3237 [HNOI2014]米特运输 题解 题目链接:P3237 [HNOI2014]米特运输 题意: 这题面是真的长啊 qwq 米特是D星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为 ...

  7. 洛谷P5520 [yLOI2019] 青原樱 题解

    洛谷P5520 [yLOI2019] 青原樱 题解 题目链接:P5520 [yLOI2019] 青原樱 题意: n n n 个空放 m m m 个物品,两两物品不能直接相邻,至少空一格 纯数学题. 看 ...

  8. 洛谷P4084 [USACO17DEC]Barn Painting G 题解

    洛谷P4084 [USACO17DEC]Barn Painting G 题解 题目链接:P4084 [USACO17DEC]Barn Painting G 题意:题意:给定一颗N个节点组成的树,3种颜 ...

  9. 洛谷P4315 月下“毛景树” 题解

    洛谷P4315 月下"毛景树" 题解 题目链接:P4315 月下"毛景树" 题意:请维护一个数据结构,支持 改第 kkk 条边的边权 结点 uuu 到 vvv ...

  10. 洛谷P3412 仓鼠找$Sugar\ II$题解(期望+统计论?)

    洛谷P3412 仓鼠找\(Sugar\ II\)题解(期望+统计论?) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327573 原题链接:洛谷P3412 ...

最新文章

  1. mysql远程服务器返回错误404未找到_远程服务器返回错误: 404错误、远程服务器返回错误:500错误、 HttpWebResponse远程服务器返回错误:(404、500) 错误。...
  2. SCART接口保护 ESD二极管选型
  3. Java 设计模式之观察者模式
  4. VTK:IO之ReadExodusData
  5. oracle linux rdac,redhat 6.4 安装RDAC
  6. db服务器作用,数据库服务器
  7. 关于docker环境下mysql的使用相关
  8. 关于CALayer导致的crash问题
  9. js控制页面滑动加载
  10. WEB入门.九 导航菜单
  11. c语言isfinite用法,C# Double.IsFinite()用法及代码示例
  12. 微观结构到应用材料力学行为
  13. Box2d源码学习一之Box2d简介
  14. IBM-PC汇编语言程序设计课后习题答案(第4、5章)
  15. 位运算的那些事(三)位掩码
  16. 扩展odoo res.partner的问题
  17. websocket-php
  18. isp调试linux程序,相机isp调试 - Linux - Firefly开源社区相机isp调试
  19. cesium实现晴,雨,雾,雪等效果
  20. Android GNSS 可视卫星星空图/卫星天顶图 原理及画法介绍

热门文章

  1. cf-645D. Robot Rapping Results Report(判断是否是惟一的拓扑序列)
  2. 怡红快绿 [转自TK's Blog]
  3. java 多定时任务_多机部署之定时任务完整方案
  4. 快递柜智能柜C语言程序,家用智能快递柜的设计与实现(含电路图)
  5. php程序的运行方法
  6. layer mobile使用方法
  7. 1958年第一台电子计算机,第一台电子计算机
  8. FireFox插件开发--弃用NPAPI
  9. [BJWC2008]王之财宝
  10. Google Chrome浏览器调试入门————转载只为自己查看方便