当前位置: 首页 > news >正文

[NOI2014] 魔法森林(LCT维护MST)

https://www.luogu.com.cn/problem/P2387

考虑按 a a a 排序加边,我们只需要维护 1 , n 1,n 1,n 的最短链就行

假如如果一直是森林那么是好做的,直接LCT即可。如果加入一条边后有环,我们可以尝试把环上最大一条边删掉。

实现的时候,我们可以把边换成点,然后把链提取出来,在平衡树内删掉最大点即可

#include<bits/stdc++.h>
using namespace std;
#ifdef LOCAL#define debug(...) fprintf(stdout, ##__VA_ARGS__)#define debag(...) fprintf(stderr, ##__VA_ARGS__)
#else#define debug(...) void(0)#define debag(...) void(0)
#endif
//#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
#define fi first
#define se second
//#define M
//#define mo
#define N 200010
struct node {int u, v, a, b; 
}e[N]; 
int n, m, i, j, k, T;
int ans, a[N], u, v; namespace LCT {
#define ls(x) (son[x][0])
#define rs(x) (son[x][1])int son[N][2], rev[N], mx[N], fa[N]; void push_down(int x) {if(rev[x]) {swap(ls(x), rs(x)); if(ls(x)) rev[ls(x)] ^= 1; if(rs(x)) rev[rs(x)] ^= 1; rev[x] = 0; }}void push_up(int x) {mx[x] = x; if(a[mx[ls(x)]] > a[mx[x]]) mx[x] = mx[ls(x)]; if(a[mx[rs(x)]] > a[mx[x]]) mx[x] = mx[rs(x)]; }bool isRoot(int x) {if(!fa[x]) return true; return ls(fa[x]) != x && rs(fa[x]) != x; }int zh(int x) {return rs(fa[x]) == x; }void Rotate(int x) {int y = fa[x], z = fa[y]; int k = zh(x), w = son[x][k ^ 1]; if(z && !isRoot(y)) son[z][zh(y)] = x; if(w) fa[w] = y, son[y][k] = w; else son[y][k] = 0; fa[x] = z; fa[y] = x; son[x][k ^ 1] = y; push_up(y); push_up(x); push_up(z); }void Splay(int x) {stack<int>sta; sta.push(x); for(int y = x; !isRoot(y); y = fa[y]) sta.push(fa[y]); while(!sta.empty()) push_down(sta.top()), sta.pop(); while(!isRoot(x)) {int y = fa[x]; if(!isRoot(y)) {if(zh(y) == zh(x)) Rotate(y); else Rotate(x); }Rotate(x); }}void access(int x) {debug("access(%d)\n", x); for(int y = 0; x; y = x, x = fa[x]) {Splay(x); rs(x) = y; push_up(x); }}void makeRoot(int x) {access(x); Splay(x); rev[x] ^= 1; }int findRoot(int x) {access(x); Splay(x); while(push_down(x), ls(x)) x = ls(x); Splay(x); return x; }bool check(int x, int y) {makeRoot(x); return findRoot(y) == x; }void Link(int x, int y) {debug("Link(%d %d)\n", x, y); makeRoot(x); fa[x] = y; }void Delete(int x) {makeRoot(x); Splay(x); push_down(x); fa[ls(x)] = fa[rs(x)] = 0; ls(x) = rs(x) = 0; }int Qrymax(int x, int y) {makeRoot(x); access(y); Splay(y); int z = mx[y]; Splay(z); return z; }void print() {int i; #ifdef LOCALdebug("(%d %d %d | %d %d)\n", fa[1], ls(1), rs(1), a[1], mx[1]); for(i = 1; i <= n + m; ++i) if(fa[i] || ls(i) || rs(i)) debug("fa[%d] = %d(%d)(%d %d) || %d %d\n", i, fa[i], isRoot(i), ls(i), rs(i), a[i], mx[i]); debug("----------------------------------------\n"); #endif}
}signed main()
{#ifdef LOCALfreopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);#endif
//	srand(time(NULL));
//	T=read();
//	while(T--) {
//
//	}n = read(); m = read(); ans = 1e9; for(i = 1; i <= n + m; ++i) LCT :: mx[i] = i; for(i = 1; i <= m; ++i) {e[i].u = read(); e[i].v = read(); e[i].a = read(); e[i].b = read(); }sort(e + 1, e + m + 1, [] (node x, node y) { return x.a < y.a; }); for(i = 1; i <= m; ++i) {u = e[i].u; v = e[i].v; a[i + n] = e[i].b; debug("(%d %d) %d %d\n", u, v, e[i].a, e[i].b); if(!LCT :: check(u, v)) {
//			debug("Link(%d %d)\n", u, v); LCT :: Link(u, i + n);
//			LCT :: print(); LCT :: Link(v, i + n); }else {int x = LCT :: Qrymax(u, v); //pathif(a[x] > e[i].b) {LCT :: Delete(x); LCT :: Link(u, i + n), LCT :: Link(v, i + n); }}
//		LCT :: print(); if(LCT :: check(1, n)) {int x = LCT :: Qrymax(1, n); debug("#### %d + %d(%d)\n", e[i].a, a[x]); ans = min(ans, e[i].a + a[x]); }}printf("%d", ans == 1e9 ? -1 : ans); return 0;
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Spring Boot 多数据源配置(JPA)
  • 数据仓库技术选型方案文档
  • 语言桥梁:探索全球最受欢迎的翻译工具,让理解更简单
  • Nginx 负载均衡+高可用 集群部署(Keepalived+LVS DR模式)
  • 【WPF动画】
  • 内存管理(三)--Linux CMA内存使用
  • 巧用xrename批量重命名下载的影视文件
  • SQL-函数
  • Open3D 基于曲率大小的特征点提取
  • 微信小程序中如何监听元素进入目标元素
  • stm32F103 串口2 中断 无法接收指定字符串 [已解决]
  • 用idea写Spark程序时,想要在控制台打印日志?
  • class 6: vue.js 3 组件化开发
  • 微服务--Nacos配置管理
  • axios返回的是promise对象如何处理?
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • axios 和 cookie 的那些事
  • canvas绘制圆角头像
  • go append函数以及写入
  • Hexo+码云+git快速搭建免费的静态Blog
  • If…else
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • Redis字符串类型内部编码剖析
  • 番外篇1:在Windows环境下安装JDK
  • 高度不固定时垂直居中
  • 基于组件的设计工作流与界面抽象
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 如何合理的规划jvm性能调优
  • 使用 Docker 部署 Spring Boot项目
  • 一份游戏开发学习路线
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • 说说我为什么看好Spring Cloud Alibaba
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • ​学习一下,什么是预包装食品?​
  • #NOIP 2014#Day.2 T3 解方程
  • #我与Java虚拟机的故事#连载14:挑战高薪面试必看
  • (2)STM32单片机上位机
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (苍穹外卖)day03菜品管理
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (四)JPA - JQPL 实现增删改查
  • (四)软件性能测试
  • (转)shell中括号的特殊用法 linux if多条件判断
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .net core使用EPPlus设置Excel的页眉和页脚
  • .net 生成二级域名
  • .net 微服务 服务保护 自动重试 Polly
  • .net/c# memcached 获取所有缓存键(keys)
  • .net操作Excel出错解决
  • .NET开源纪元:穿越封闭的迷雾,拥抱开放的星辰
  • .Net中间语言BeforeFieldInit
  • [23] 4K4D: Real-Time 4D View Synthesis at 4K Resolution