Description

给定一张n个点,m条边的无向图,求出边权最大值和最小值差值最小的生成树

Solution

LCT+并查集

按照最小生成树的思路,先将边按照边权从小到大排序,然后顺序考虑每一条边

如果当前这条边的两个端点没有连通,那么直接连通

如果两个端点已经连通,我们加上这条边会形成一个环,那么为了让“边权最大值和最小值差值”尽可能小,我们可以将这个环上最短的一条边删掉,换成这条边(显然是对的)

维护最小值可以通过LCT实现,连边、短边也是LCT的基本操作

当目前的边已经是一棵树的时候更新答案即可完成

Code

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 const int N = 50010;
  5 const int M = 200010;
  6 inline int read() {
  7     int ret = 0, op = 1;
  8     char c = getchar();
  9     while (!isdigit(c)) {
 10         if (c == '-') op = -1;
 11         c = getchar();
 12     }
 13     while (isdigit(c)) {
 14         ret = (ret << 3) + (ret << 1) + c - '0';
 15         c = getchar();
 16     }
 17     return ret * op;
 18 }
 19 struct Edge {
 20     int from, to, dis;
 21     bool operator <(const Edge &x) const {
 22         return dis < x.dis;
 23     }
 24 } edge[M];
 25 struct LCT {
 26     int fa, val, minn, ch[2], tag;
 27 } a[N + M];
 28 int n, m, s[N + M], f[N];
 29 int vis[M];
 30 int find(int x) {
 31     if (f[x] != x) return f[x] = find(f[x]);
 32     return f[x];
 33 }
 34 inline int isnroot(int now) {
 35     return a[a[now].fa].ch[0] == now || a[a[now].fa].ch[1] == now;
 36 }
 37 inline int get(int x, int y) {
 38     return a[x].val < a[y].val ? x : y;
 39 }
 40 inline void update(int now) {
 41     int l = a[now].ch[0];
 42     int r = a[now].ch[1];
 43     a[now].minn = get(now, get(a[l].minn, a[r].minn));
 44 }
 45 inline void rev(int now) {
 46     swap(a[now].ch[0], a[now].ch[1]);
 47     a[now].tag ^= 1;
 48 }
 49 inline void pushdown(int now) {
 50     if (a[now].tag) {
 51         if (a[now].ch[0]) rev(a[now].ch[0]);
 52         if (a[now].ch[1]) rev(a[now].ch[1]);
 53         a[now].tag = 0;
 54     }
 55 }
 56 void rotate(int x) {
 57     int y = a[x].fa;
 58     int z = a[y].fa;
 59     int xson = a[y].ch[1] == x;
 60     int yson = a[z].ch[1] == y;
 61     int B = a[x].ch[xson ^ 1];
 62     if (isnroot(y)) a[z].ch[yson] = x;
 63     a[x].ch[xson ^ 1] = y;
 64     a[y].ch[xson] = B;
 65     if (B) a[B].fa = y;
 66     a[y].fa = x;
 67     a[x].fa = z;
 68     update(y);
 69 }
 70 void splay(int x) {
 71     int y = x, z = 0;
 72     s[++z] = y;
 73     while (isnroot(y)) y = a[y].fa, s[++z] = y;
 74     while (z) pushdown(s[z--]);
 75     while (isnroot(x)) {
 76         y = a[x].fa;
 77         z = a[y].fa;
 78         if (isnroot(y))
 79             (a[z].ch[0] == y) ^ (a[y].ch[0] == x) ? rotate(x) : rotate(y);
 80         rotate(x);
 81     }
 82     update(x);
 83 }
 84 void access(int x) {
 85     for (register int y = 0; x; y = x, x = a[x].fa) {
 86         splay(x); a[x].ch[1] = y; update(x);
 87     }
 88 }
 89 void makeroot(int x) {
 90     access(x);
 91     splay(x);
 92     rev(x);
 93 }
 94 void link(int i) {
 95     makeroot(edge[i].from);
 96     a[edge[i].from].fa = i + N;
 97     a[i + N].fa = edge[i].to;
 98 }
 99 void cut(int i) {
100     access(edge[i - N].from);
101     splay(i);
102     a[a[i].ch[1]].fa = a[a[i].ch[0]].fa = 0;
103     a[i].ch[0] = a[i].ch[1] = 0;
104 }
105 int main() {
106     n = read(); m = read();
107     for (register int i = 0; i <= n; ++i) f[i] = i, a[i].val = 2147483647;
108     for (register int i = 1; i <= m; ++i) {
109         edge[i].from = read(); edge[i].to = read(); edge[i].dis = read();
110     }
111     sort(edge + 1, edge + m + 1);
112     int sum = 0, ans = 0, k = 1;
113     for (register int i = 1; i <= m; ++i) {
114         a[i + N].val = edge[i].dis;
115         int x = edge[i].from;
116         int y = edge[i].to;
117         if (find(x) != find(y)) {
118             vis[i] = 1;
119             sum++;
120             link(i);
121             f[f[x]] = f[y];
122             if (sum == n - 1) ans = edge[i].dis - edge[k].dis;
123         }
124         else {
125             if (x == y) continue ;
126             vis[i] = 1;
127             makeroot(x);
128             access(y); splay(y);
129             vis[a[y].minn - N] = 0;
130             while (vis[k] == 0) ++k;
131             cut(a[y].minn); link(i);
132             if (sum == n - 1) ans = min(ans, edge[i].dis - edge[k].dis);
133         }
134     }
135     printf("%d\n", ans);
136     return 0;
137 }

AC Code

转载于:https://www.cnblogs.com/shl-blog/p/11354557.html

【洛谷P4234】最小差值生成树相关推荐

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

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

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

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

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

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

  4. 洛谷 1351 联合权值

    [题解] 每个点维护各个儿子的前后缀最大值.权值和,这样就可以统计儿子之间相乘的答案.然后每个节点再乘它的祖父的权值去更新答案即可. 1 #include<cstdio> 2 #inclu ...

  5. 洛谷P1351 联合权值(树形dp)

    题意 题目链接 Sol 一道很简单的树形dp,然而被我写的这么长 分别记录下距离为\(1/2\)的点数,权值和,最大值.以及相邻儿子之间的贡献. 树形dp一波.. #include<bits/s ...

  6. 洛谷 1351 联合权值——树形dp

    题目:https://www.luogu.org/problemnew/show/P1351 对拍了一下,才发现自己漏掉了那种拐弯的情况. #include<iostream> #incl ...

  7. 信息学奥赛一本通 1956:【11NOIP普及组】表达式的值 | 洛谷 P1310 [NOIP2011 普及组] 表达式的值

    [题目链接] ybt 1956:[11NOIP普及组]表达式的值 洛谷 P1310 [NOIP2011 普及组] 表达式的值 [题目考点] 表达式树 由带括号的中缀表达式构建表达式树 [解题思路] 思 ...

  8. 信息学奥赛一本通 1962:【13NOIP普及组】表达式求值 | 洛谷 P1981 [NOIP2013 普及组] 表达式求值

    [题目链接] ybt 1962:[13NOIP普及组]表达式求值 洛谷 P1981 [NOIP2013 普及组] 表达式求值 [题目考点] 栈 中缀表达式转后缀表达式,后缀表达式求值 中缀表达式求值 ...

  9. 【杂题总汇】NOIP2013(洛谷P1967) 货车运输

    [洛谷P1967] 货车运输 重做NOIP提高组ing... +传送门-洛谷P1967+ ◇ 题目(copy from 洛谷) 题目描述 A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道 ...

  10. 信息学奥赛一本通 1392:繁忙的都市(city) | 洛谷 P2330 [SCOI2005]繁忙的都市

    [题目链接] ybt 1392:繁忙的都市(city) 洛谷 P2330 [SCOI2005]繁忙的都市 [题目考点] 1. 图论 最小生成树 [解题思路] 将题目叙述转为图论概念,交叉路口为顶点,道 ...

最新文章

  1. LeetCode 滑动窗口(Sliding Window)类问题总结
  2. [译] MDC-101 Flutter:Material Components(MDC)基础(Flutter)
  3. DYNP_VALUES_READ
  4. 笔记-高项案例题-2015年上-计算题
  5. C++ cin cout
  6. 远控免杀专题(15)-DKMC免杀
  7. MySQL not in查询不出数据(MySQL not in 无效)
  8. 用c语言写出一个榜单程序,C语言依然位居榜单前列,依然值得程序员学习
  9. bzoj4569 [Scoi2016]萌萌哒 并查集+st表
  10. buck变换器设计matlab_[Fundamental of Power Electronics]-PART I-6.变换器电路-6.2 变换器简单罗列 - Yangswear...
  11. oracle 赋予dorp,oracle表空间(tablespace)的增删改查(create/drop/rename,move/select)
  12. Python天天美味(4) - isinstance判断对象类型
  13. Linux下autoconf与automake
  14. C++ 之父即将开始直播,请就位!
  15. 设计模式—结构型模式概述(思维导图)
  16. 《vSphere性能设计:性能密集场景下CPU、内存、存储及网络的最佳设计实践》一1.2.4 存储...
  17. Python使用requests发送post请求
  18. 小米笔记本系统win10家庭版升级为企业版(专业版)
  19. 关于三方支付做的一个小总结,后期不断完善更新
  20. 43-圣诞老人的礼物

热门文章

  1. 虚拟机中试用windows 8(视频)
  2. 图论1:哥尼斯堡七桥问题的证明
  3. 玛雅历 —— C++
  4. 中国诺贝尔物理学奖所有获得者名单(转)
  5. 计算机英语解读,解释计算机Windows的学习英语
  6. “您未被授权查看该页,您不具备使用所提供的凭据查看该目录或页的权限” -- 解决办法
  7. Windows系统封装步骤
  8. [Java学习] 小型社交平台,能发帖、查看、评论、删除帖子等功能
  9. 【转载】电磁波中的波段划分:L波段、S波段、C波段、X波段、Ku波段、K波段、Ka波段 等等
  10. opencv学习笔记(一) 环境配置/打开一张图片/github(git)初探