LCT维护生成树

把边从小到大排序,然后一条一条加边,如果成环就把环上最小的删了,我们得到的第一个生成树就是最小生成树。

然后之后每一条边都比前面的生成树的最大边大,我们用这条边的权值减去生成树里最小的,更新答案即可。

因为要维护的是最小值,用排序之后的性质,下表小的值更小来pushup

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
#define FAST_IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;
typedef long long LL;
inline int lowbit(int x){ return x & (-x); }
inline int read(){int ret = 0, w = 0; char ch = 0;while(!isdigit(ch)){w |= ch == '-', ch = getchar();}while(isdigit(ch)){ret = (ret << 3) + (ret << 1) + (ch ^ 48);ch = getchar();}return w ? -ret : ret;
}
inline int lcm(int a, int b){ return a / __gcd(a, b) * b; }
template <typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){A ans = 1;for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;return ans;
}
const int N = 500005;
int n, m, cnt, tot, cur, ans, val[N], fa[N], ch[N][2], rev[N], id[N], st[N];
bool vis[N];
struct Edge {int u, v, w;bool operator < (const Edge &rhs) const {return w < rhs.w;}
} e[N];int newNode(int x){++ tot;val[tot] = x, id[tot] = tot;rev[tot] = ch[tot][0] = ch[tot][1] = fa[tot] = 0;return tot;
}bool isRoot(int x){return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
}void reverse(int x){rev[x] ^= 1, swap(ch[x][0], ch[x][1]);
}void push_up(int x){id[x] = x;int l = ch[x][0], r = ch[x][1];if(id[l] > n && (id[x] <= n || id[x] > id[l])) id[x] = id[l];if(id[r] > n && (id[x] <= n || id[x] > id[r])) id[x] = id[r];
}void push_down(int x){if(rev[x]){int l = ch[x][0], r = ch[x][1];if(l) reverse(l);if(r) reverse(r);rev[x] ^= 1;}
}void rotate(int x){int y = fa[x], z = fa[y], p = (ch[y][1] == x) ^ 1;ch[y][p^1] = ch[x][p], fa[ch[x][p]] = y;if(!isRoot(y)) ch[z][ch[z][1] == y] = x;fa[x] = z, fa[y] = x, ch[x][p] = y;push_up(y), push_up(x);
}void splay(int x){int pos = 0; st[++pos] = x;for(int i = x; !isRoot(i); i = fa[i]) st[++pos] = fa[i];while(pos) push_down(st[pos--]);while(!isRoot(x)){int y = fa[x], z = fa[y];if(!isRoot(y)){(ch[y][0] == x) ^ (ch[z][0] == y) ? rotate(x) : rotate(y);}rotate(x);}push_up(x);
}void access(int x){for(int p = 0; x; p = x, x = fa[x]){splay(x), ch[x][1] = p, push_up(x);}
}void makeRoot(int x){access(x), splay(x), reverse(x);
}void link(int x, int y){makeRoot(x);fa[x] = y;
}int findRoot(int x){access(x), splay(x);while(ch[x][0]) push_down(x), x = ch[x][0];splay(x);return x;
}void split(int x, int y){makeRoot(x), access(y), splay(y);
}bool isConnect(int x, int y){makeRoot(x);return findRoot(y) == x;
}int main(){n = read(), m = read();for(int i = 1; i <= m; i ++){e[i].u = read(), e[i].v = read(), e[i].w = read();}ans = INF, cur = 1;sort(e + 1, e + m + 1);for(int i = 1; i <= n; i ++) newNode(0);for(int i = 1; i <= m; i ++) newNode(e[i].w);for(int i = 1; i <= m; i ++){int u = e[i].u, v = e[i].v, w = e[i].w;if(u == v) continue;if(!isConnect(u, v)){link(u, i + n), link(i + n, v);vis[i] = true, cnt ++;}else{split(u, v);int tmp = id[v];splay(tmp);fa[ch[tmp][0]] = fa[ch[tmp][1]] = 0;ch[tmp][0] = ch[tmp][1] = 0;vis[tmp - n] = false, vis[i] = true;link(u, i + n), link(i + n, v);while(!vis[cur]) cur ++;}if(cnt == n - 1) ans = min(ans, w - e[cur].w);}cout << ans << endl;return 0;
}

转载于:https://www.cnblogs.com/onionQAQ/p/11232377.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. 微信小程序原生组件swiper在mpvue工程中使用注意事项
  2. 【记忆断层、记忆裂痕】
  3. classpath: spring 中的查找方式
  4. P4449 于神之怒加强版
  5. tf.TensorArray
  6. 【BZOJ4025】二分图(可撤销并查集+线段树分治)
  7. .NET设计模式(9):桥接模式(Bridge Pattern)(转)
  8. Javascript特效:简单的匀速平移动画
  9. net4.0的从客户端中检测到有潜伏危险的 Request.Form
  10. 3D动作绑定_【动捕小灶】动作捕捉数据应用到动画流程详解
  11. 树莓派搭建kms服务器
  12. 2022年低功耗软路由cpu一览
  13. 微信开放平台申请网站应用
  14. matplotlib工具栏源码探析一(禁用工具栏、默认工具栏和工具栏管理器三种模式的差异)
  15. 虚幻蓝图数据传递_数据产品的战略蓝图
  16. 牛客网 赛码在线编程中数据读取问题
  17. aspx网页背景图片设置代码_Vue+CSS3制作双螺旋DNA动画:代码详解和基础知识复习
  18. java删除linux上的文件或文件夹工具类
  19. 【XP系统的网络设置技巧】
  20. git从远端仓库拉取代码, 切换其他分支(develop)注意点

热门文章

  1. HTB靶机:RainyDay
  2. 缓存和数据库刷新的顺序 及阿里OCS介绍
  3. 国家队上场——国家测绘局网络地图网站评测
  4. java的duplicate用法_Java ByteBuffer duplicate()用法及代码示例
  5. 【程序员面试金典】有一个XxY的网格,一个机器人只能走格点且只能向右或向下走,要从左上角走到右下角。请设计一个算法,计算机器人有多少种走法。注意这次的网格中有些障碍点是不能走的。
  6. python双色球数据抓取及模拟生成高概率的号码
  7. python字符串后面添加字符串_Python字符串中添加、插入特定字符的方法
  8. 51.com数十高层离职幕后:3年内乱因扩张失败,互联网营销
  9. quickchm乱码问题
  10. 搭建简易客户端从tftp服务器中下载文件