[洛谷P4234]最小差值生成树
给定一个标号为从$1$到$n$的、有$m$条边的无向图,求边权最大值与最小值的差值最小的生成树。
做法类似魔法森林,首先求出来最小生成树,然后每次加入一条边,断掉环上最小边并更新答案
这个过程我用两个堆维护的
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define M 500010 7 #define ls ch[x][0] 8 #define rs ch[x][1] 9 using namespace std; 10 int n,m,ans,top,cnt; 11 int st[M],f[M],fa[M],rev[M],minn[M],val[M],id[M],ch[M][2]; 12 struct node{int v;}; 13 priority_queue<node>q1,q2; 14 bool operator < (node a1,node a2) { 15 return a1.v>a2.v; 16 } 17 void heap_pop(int v) { 18 q1.push((node){v}); 19 } 20 void heap_push(int v) { 21 q2.push((node){v}); 22 } 23 int heap_top() { 24 while(!q1.empty()) { 25 int x1=q1.top().v,x2=q2.top().v; 26 if(x1==x2) q1.pop(),q2.pop(); 27 else break; 28 } 29 return q2.top().v; 30 } 31 struct point{ 32 int u,v,w; 33 }a[M]; 34 bool cmp(point a1,point a2) { 35 return a1.w<a2.w; 36 } 37 int find(int x) { 38 return fa[x]==x?x:fa[x]=find(fa[x]); 39 } 40 void update(int x) { 41 minn[x]=val[x];id[x]=x; 42 if(ls&&minn[ls]<minn[x]) minn[x]=minn[ls],id[x]=id[ls]; 43 if(rs&&minn[rs]<minn[x]) minn[x]=minn[rs],id[x]=id[rs]; 44 } 45 void pushdown(int x) { 46 if(rev[x]) { 47 if(ls) rev[ls]^=1; 48 if(rs) rev[rs]^=1; 49 swap(ls,rs),rev[x]^=1; 50 } 51 } 52 int get(int x) { 53 return ch[f[x]][1]==x; 54 } 55 bool is_root(int x) { 56 return ch[f[x]][0]!=x&&ch[f[x]][1]!=x; 57 } 58 void rotate(int x) { 59 int old=f[x],oldf=f[old],k=get(x); 60 if(!is_root(old)) ch[oldf][ch[oldf][1]==old]=x; 61 ch[old][k]=ch[x][k^1],f[ch[old][k]]=old; 62 ch[x][k^1]=old,f[old]=x,f[x]=oldf; 63 update(old),update(x); 64 } 65 void splay(int x) { 66 st[top=1]=x; 67 for(int i=x;!is_root(i);i=f[i]) st[++top]=f[i]; 68 for(int i=top;i>=1;i--) pushdown(st[i]); 69 for(int fa;!is_root(x);rotate(x)) 70 if(!is_root(fa=f[x])) 71 rotate(get(x)==get(fa)?fa:x); 72 } 73 void access(int x) { 74 for(int y=0;x;y=x,x=f[x]) 75 splay(x),ch[x][1]=y,update(x); 76 } 77 void makeroot(int x) { 78 access(x);splay(x);rev[x]^=1; 79 } 80 void spilt(int x,int y) { 81 makeroot(x);access(y);splay(y); 82 } 83 void link(int x,int y) { 84 makeroot(x);f[x]=y;splay(x); 85 } 86 void cut(int x,int y) { 87 spilt(x,y);f[x]=ch[y][0]=0; 88 } 89 int query(int x,int y) { 90 spilt(x,y);return id[y]; 91 } 92 int main() { 93 scanf("%d%d",&n,&m); 94 for(int i=1;i<=m;i++) 95 scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w); 96 sort(a+1,a+1+m,cmp); 97 memset(minn,63,sizeof(minn)); 98 memset(val,63,sizeof(val)); 99 memset(&ans,0x7f,sizeof(ans)); 100 for(int i=1;i<=n;i++) fa[i]=i; 101 for(int i=1;i<=m;i++) id[i+n]=i+n,val[i+n]=a[i].w; 102 for(int i=1;i<=m;i++) { 103 int x=a[i].u,y=a[i].v; 104 if(find(x)==find(y)) { 105 int ID=query(x,y); 106 cut(a[ID-n].u,ID),cut(a[ID-n].v,ID); 107 link(x,i+n),link(y,i+n); 108 heap_pop(val[ID]); 109 heap_push(val[i+n]); 110 } 111 else { 112 fa[find(x)]=find(y); 113 link(x,i+n),link(y,i+n); 114 heap_push(val[i+n]); 115 cnt++; 116 } 117 if(cnt==n-1) { 118 ans=min(ans,a[i].w-heap_top()); 119 } 120 } 121 printf("%d\n",ans); 122 return 0; 123 }
转载于:https://www.cnblogs.com/Slrslr/p/10022180.html
[洛谷P4234]最小差值生成树相关推荐
- 洛谷.4234.最小差值生成树(LCT)
题目链接 先将边排序,这样就可以按从小到大的顺序维护生成树,枚举到一条未连通的边就连上,已连通则(用当前更大的)替换掉路径上最小的边,这样一定不会更差. 每次构成树时更新答案.答案就是当前边减去生成树 ...
- 洛谷P5633 最小度限制生成树 题解
洛谷P5633 最小度限制生成树 题解 题目链接:P5633 最小度限制生成树 题意: 给你一个有 n n n 个节点, m m m 条边的带权无向图,你需要求得一个生成树,使边权总和最小,且满足编号 ...
- 洛谷 1351 联合权值
[题解] 每个点维护各个儿子的前后缀最大值.权值和,这样就可以统计儿子之间相乘的答案.然后每个节点再乘它的祖父的权值去更新答案即可. 1 #include<cstdio> 2 #inclu ...
- 洛谷P1351 联合权值(树形dp)
题意 题目链接 Sol 一道很简单的树形dp,然而被我写的这么长 分别记录下距离为\(1/2\)的点数,权值和,最大值.以及相邻儿子之间的贡献. 树形dp一波.. #include<bits/s ...
- 洛谷 1351 联合权值——树形dp
题目:https://www.luogu.org/problemnew/show/P1351 对拍了一下,才发现自己漏掉了那种拐弯的情况. #include<iostream> #incl ...
- 信息学奥赛一本通 1956:【11NOIP普及组】表达式的值 | 洛谷 P1310 [NOIP2011 普及组] 表达式的值
[题目链接] ybt 1956:[11NOIP普及组]表达式的值 洛谷 P1310 [NOIP2011 普及组] 表达式的值 [题目考点] 表达式树 由带括号的中缀表达式构建表达式树 [解题思路] 思 ...
- 信息学奥赛一本通 1962:【13NOIP普及组】表达式求值 | 洛谷 P1981 [NOIP2013 普及组] 表达式求值
[题目链接] ybt 1962:[13NOIP普及组]表达式求值 洛谷 P1981 [NOIP2013 普及组] 表达式求值 [题目考点] 栈 中缀表达式转后缀表达式,后缀表达式求值 中缀表达式求值 ...
- 【杂题总汇】NOIP2013(洛谷P1967) 货车运输
[洛谷P1967] 货车运输 重做NOIP提高组ing... +传送门-洛谷P1967+ ◇ 题目(copy from 洛谷) 题目描述 A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道 ...
- 信息学奥赛一本通 1392:繁忙的都市(city) | 洛谷 P2330 [SCOI2005]繁忙的都市
[题目链接] ybt 1392:繁忙的都市(city) 洛谷 P2330 [SCOI2005]繁忙的都市 [题目考点] 1. 图论 最小生成树 [解题思路] 将题目叙述转为图论概念,交叉路口为顶点,道 ...
最新文章
- 三代测序之微生物基因组 de novo 测序
- poj 2411 Mondriaan#39;s Dream 【dp】
- 挖掘 OSINT 金矿——实习生和社交媒体
- Eclipse自动生成返回值对象与补全与加注释
- vue data变量之间相互赋值或进行数据联动
- Lintcode14 First Position of Target Solution 题解
- java http get 图片_http协议get方法获取图片并保存到本地
- 【免费分享】收集整理的117套各类微信小程序模板源码分享
- java合并2个txt文本,Java实现多个文档合并输出到一个文档
- 谈MDM主数据管理系统、BI、大数据、SOA之间的关系
- 推荐几个好用又好玩的vscode插件!
- android als传感器,环境光传感器(ALS)背光控制系统解决方案
- guava-retry介绍
- java课程设计 雍俊海_java课程设计模拟科学计算器【参考】.doc
- 汇编语言-用Si和Di实现字符串复制到其他的区域
- 终于学会数组的使用啦~~~------C语言数组学习笔记详解
- POI实现 Excel插入图片
- Lucene学习——IKAnalyzer中文分词(一)
- 计算机工程学院文艺例会,信息科学与工程学院学生会学生会全体例会暨部门风采展示大会...
- 干货|chrome浏览器模拟定位
热门文章
- java基础的知识_Java基础知识点(一)
- JSch连接不上Linux服务器,windows 下 java程序jsch连接远程linux服务器执行shell命令
- 爬虫教程 python3_Python3网络爬虫(四): 登录
- 日志记录到字段变更_Wal日志解析工具开源: Walminer
- cad2008加载 et拓展工具_译文:8个值得推荐的用于前端开发的性能分析工具「渡一教育」...
- Apollo开发平台授权管理的使用
- Linux中locate命令查找文件位置
- C++ 构造函数与析构函数
- RSA大会:中国信息安全的“走出去”与“学回来”
- 译 | 像使用一台主机一样管理集群