经典LCA例题:P4180 [BJWC2010] 严格次小生成树

2023-05-16

Acwing:严格次小生成树(求两点间路径上最大边的权值)(模板)

洛谷:严格次小生成树

在这里插入图片描述

  • 求两点间路径上最大边的权值,就不能通过前缀和了,会丢失信息。每个结点存到其他结点的路径最大边权又占用过多空间 O ( n 2 ) O(n^2) O(n2)

  • 因此学习下倍增优化存点的思想,将这空间二进制压缩成 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)

  • 维护一个 d [ i ] [ j ] d[i][j] d[i][j] ,维护从 i 点往上跳 2 j 2^j 2j 步这条路径上的最大边权

  • 如果是求 严 格 次 小 树 严格次小树 那就要维护一个 最 大 最大 d1 和一个 次 大 次大 d2 数组。最后 lca 求最近公共祖先时,随时记录每一条路径(二进制压缩过,但累计在一起信息不会丢失),就能得出两点间路径的最大和次大边权了

代码:

#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define sca scanf
#define pri printf
#define ul u << 1
#define ur u << 1 | 1
//#pragma GCC optimize(2)
//[博客地址](https://blog.csdn.net/weixin_51797626?t=1) 
using namespace std;

typedef long long ll;
typedef pair<int, int> PII;

const int N = 100010, M = N << 1, MM = 3000010;
int INF = 0x3f3f3f3f, mod = 100003;
ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, k, T, S, D;
int h[N], e[M], ne[M], w[M], idx;
int p[N], dep[N], q[N];
int fa[N][17], d1[N][17], d2[N][17];

struct edge
{
	int l, r, w;
	bool tree;
	bool operator <(const edge& t)const {
		return w < t.w;
	}
}ed[N * 3];

void add(int a, int b, int x) {
	e[idx] = b, w[idx] = x, ne[idx] = h[a], h[a] = idx++;//bug —— h[a]++
}

int find(int x) {
	if (p[x] != x)p[x] = find(p[x]);
	return p[x];
}

ll kruskal() {
	mem(h, -1);
	sort(ed, ed + m);
	for (int i = 1; i <= n; i++)p[i] = i;

	ll res = 0;
	for (int i = 0; i < m; i++) {
		int a = ed[i].l, b = ed[i].r, w = ed[i].w;
		int fa = find(a), fb = find(b);
		if (fa != fb) {
			res += w;
			ed[i].tree = true;
			add(a, b, w), add(b, a, w);//随时建这颗最小生成树
			p[fa] = fb;
		}
	}
	return res;
}

void bfs() {
	mem(dep, 0x3f);
	dep[0] = 0, dep[1] = 1;
	int hh = 0, tt = 0;
	q[tt++] = 1;

	while (hh < tt)
	{
		int t = q[hh++];
		for (int i = h[t]; ~i; i = ne[i]) {
			int j = e[i];
			if (dep[j] > dep[t] + 1) {
				dep[j] = dep[t] + 1;
				q[tt++] = j;

				fa[j][0] = t;
				d1[j][0] = w[i], d2[j][0] = -INF;
				for (int k = 1; k <= 16; k++) {
					int anc = fa[j][k - 1];
					fa[j][k] = fa[anc][k - 1];

					//j 跳 2^k 步可以拆分成两部分:
					//先跳 2^k-1 步到anc点,再跳 2^k-1 步到终点
					//两段跳跃都有一个区间最大次大值,都记录下来
					int dist[] = { d1[j][k - 1],d2[j][k - 1],d1[anc][k - 1],d2[anc][k - 1] };
					d1[j][k] = d2[j][k] = -INF;//不能忘记此 k 处最大次大的初始化

					for (int u = 0; u < 4; u++) { //枚举每一种再维护新最大次大即可
						int d = dist[u];
						if (d > d1[j][k])d2[j][k] = d1[j][k], d1[j][k] = d;
						else if (d != d1[j][k] && d > d2[j][k])d2[j][k] = d;
					}
				}
			}
		}
	}
}

int lca(int a, int b, int x) {
	int distan[N * 2];//此处如果用vector的话测12组数据会多出400多ms的常数时间
	//容器还是要少用啊
	int cnt = 0;
	if (dep[a] < dep[b])swap(a, b);
	for (int j = 16; j >= 0; j--)
		if (dep[fa[a][j]] >= dep[b]) {
			distan[cnt++] = d1[a][j];//向上跳一段距离,这段距离的最大次大都记录下来
			distan[cnt++] = d2[a][j];
			a = fa[a][j];
		}
	if (a != b) {
		for (int j = 16; j >= 0; j--)
			if (fa[a][j] != fa[b][j]) {
				distan[cnt++] = d1[a][j];
				distan[cnt++] = d2[a][j];
				distan[cnt++] = d1[b][j];
				distan[cnt++] = d2[b][j];
				a = fa[a][j], b = fa[b][j];
			}
		distan[cnt++] = d1[a][0];
		distan[cnt++] = d1[b][0];
		//distan[cnt++](d2[a][0]);
		//不需要添加这段次大,因为只向上跳一步,显然只有最大没有次大
	}
	
	//对这样全部记录的数据,显然不会漏情况,肯定能得到 a 点到 b 点的最大次大
	int dist1 = -INF, dist2 = -INF;
	for (int i = 0; i < cnt; i++) {
		int d = distan[i];
		if (d > dist1)dist2 = dist1, dist1 = d;
		else if (d != dist1 && d > dist2)dist2 = d;
	}

	//bug —— dist1 < x ,显然若求次小生成树,添加的非树边 x 要大于树中找到的最大次大边
	if (x > dist1)return x - dist1;
	if (x > dist2)return x - dist2;
	return INF;
}

int main() {
	cinios;

	cin >> n >> m;
	for (int i = 0; i < m; i++) {
		int a, b, x;
		cin >> a >> b >> x;
		ed[i] = { a,b,x };
	}
	
	ll sum = kruskal();
	bfs();

	ll ans = LNF;
	for (int i = 0; i < m; i++) {
		if (!ed[i].tree) {
			int a = ed[i].l, b = ed[i].r, w = ed[i].w;
			ans = min(ans, sum + lca(a, b, w));//lca返回的是删去边加新边之后的增加值
		}
	}
	cout << ans;

	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

经典LCA例题:P4180 [BJWC2010] 严格次小生成树 的相关文章

  • 全网最快的M1 MacBook Air详细测评

    简要总结这款 M1 MacBook Air xff1a 1 M1性能表现超出预期的好 xff0c 速度快到堪称恐怖 2 与Intel Mac一样功能强大 xff0c 甚至更强大 3 M1发热大幅降低 xff0c 续航大幅提升 4 兼容性不是
  • Mac技巧|如何阻止 iCloud 同步某个文件夹?

    使用 iCloud 的过程中 xff0c 难免遇到有些文件夹你不希望同步 比如游戏制作 xff0c 视频剪辑等的工程文件 xff0c iCloud 的持续同步机制会使得这些文件夹中的部分文件持续处于被上传且不可用状态 今天小编就给大家带来了
  • parallels desktop M1版安装Windows10教程

    近期有些朋友购入了新的M1 mac xff0c 可发现无法安装windows 现在 xff0c Parallels发布了与M1 Mac兼容的Parallels 16的技术预览版本 xff0c 可以安装ARM版本的win10 接下来 xff0
  • macOS怎样备份?备份Mac文件的最佳方法

    备份macOS绝不是一个坏主意 xff0c 您的机器可能会损坏 xff0c 故障或变得更糟 无论出现什么问题 xff0c 备份都可以帮助您恢复正常工作 如何使用Time Machine和iCloud备份Mac 要使用Time Machine
  • Office 2019 for Mac激活失败,显示未找到许可证怎么办?

    无法激活office 2019 xff1f office 2019激活后提示找不到许可证 xff1f 今日小编找到一个解决办法 xff1a 原来是在启动程序中注册了office的授权系统监控程序 com microsoft office l

随机推荐

  • Mac 外接显示器色彩不正常解决方案

    使用 MacBook和MacMini使用外接第三方非 Apple 认证的显示器会有色彩问题 xff0c 可能是显示器颜色整体发灰 xff0c 也有可能绿色特别绿 这是因为Apple封闭的系统识别的显示器较少 xff0c 第三方厂商也未很好的
  • mybatis-xml配置

    xff08 一 xff09 先配置datasource properties配置文件 xff1a xff08 此步可省略 xff09 jdbc driver 61 com mysql jdbc Driver jdbc url 61 jdbc
  • ArchiCAD 24 Mac版3D建筑模型设计和分析软件新功能介绍

    ArchiCAD 24 Mac破解版全新上线 xff0c 有哪些新增功能 xff1f 小编给大家带来了这篇ArchiCAD 24 Mac版3D建筑模型设计和分析软件新功能介绍的文章 xff0c 希望可以帮到你 设计 创建集成模型 使用Arc
  • MacBook不断重启的 5 个原因以及如何解决此问题

    您的 Mac 是否突然无故重启 xff1f 您外出回来时 xff0c 突然发现您的 Mac 正在神秘地关闭并重新启动 xff0c 这非常令人生气 如果重新启动问题变得更加严重 xff0c 您的 MacBook可能根本无法使用 小编将为您带来
  • 如何使用Super Vectorizer在Mac上快速矢量化图像?

    如何在 Mac 上将 PDF 转换为SVG矢量 xff1f 有需要的朋友快来跟小编看看具体做法吧 xff01 步骤 1 xff1a 在 Mac 上打开 Super Image Vectorizer 将图像文件导入 Super Vectori
  • Mac电脑怎么使用ping命令?

    电脑出问题了 xff0c 上不了网 xff0c 想排查下电脑的问题出在哪儿就需要用到ping xff0c 但是如果是Mac电脑该如何ping呢 xff1f 其实在Mac 自带的 终端 中使用ping命令 xff0c 下面小编教你如何在Mac
  • 安装VMware Workstation Pro 16 教程,Ubuntu 18 桌面版安装教程

    目录 1 VMware Workstation 16 Pro 安装教程 2 Ubuntu 18 桌面版安装教程 1 VMware Workstation 16 Pro 安装教程 1 第一步 xff1a 到官网进行下载软件 xff0c 下载
  • STM32 创建LED工程,点亮LED

    容忍5V电压 FT 61 FIve Tolerate 允许5V 寄存器就是特殊的存储器 上拉输入和下拉输入 如果输入啥都不接 xff0c IO口输入电平极容易受外部电平干扰 xff0c 加上拉电阻就是为了保护输入引脚的电平 为了避免引脚悬空
  • C语言枚举使用技巧

    什么是C语言枚举 C语言枚举是一种用户自定义数据类型 xff0c 它允许程序员定义一个变量 xff0c 并将其限制为一组预定义的常量 这些常量被称为 枚举值 xff0c 并且可以通过名称进行引用 在C语言中 xff0c 枚举值是整数类型 x
  • 关于win10系统打开VMware虚拟机蓝屏的解决方案

    先说结论 xff1a 不要急着更改系统配置甚至重装系统 xff0c 首先检查自己的VMware版本 xff0c 如果为16 1或以前 xff0c 请将原先的版本升级为VMware17 0版本 xff01 xff01 xff01 本人当前电脑
  • 洛谷P1025

    这道题类似于把n个苹果放到k个盘子里且不能空盘子的问题 递归 xff08 dfs xff09 做法 include lt bits stdc 43 43 h gt define LL long long using namespace st
  • windows权限维持之shift后门

    原理 xff1a 沾滞键的目的是为了帮助那些按键有困难的人设计的 xff0c 在Windows系统下连续按5次shift键后 xff0c 系统就会执行C Windows System32下的sethc exe xff0c 也就是启用了沾滞键
  • PostgreSQL数据库smallint、bigint转到Oracle,要用什么类型替代? 是number么,那长度分别是多少?...

    个人意见 xff0c 仅供参考 xff1a smallint是有符号或无符号2字节的整数 xff0c 范围是0 xff5e 65 536 xff0c 5位整数 bigint是有符号或无符号8字节的整数 xff0c 范围是0 xff5e 18
  • 网络安全计算机基础

    计算机网络概念 xff1a 实际上是将分布在不同地理位置 xff0c 且具有独立功能的计算机 通过通信链路以及通信设备 xff0c 在网络操作系统 xff0c 网络管理软件及网络通信协议的管理和协调下实现信息传输与资源共享形成的计算机系统
  • ImportError:No module named ‘PIL‘

    运行时报错 xff1a ImportError No module named 39 PIL 原因是缺失一个pillow的数据包 xff0c 不能直接 pip install PIL xff0c 会提示找不到这个安装包 xff0c 需使用如
  • c++中#与##的作用

    1 c 43 43 中 用于把转换成字符串 define T A A 没有使用 using namespace std int main cout lt lt 34 T 2 34 lt lt T 2 lt lt endl cout lt l
  • 人工智能实验——八数码难题

    人工智能实验 八数码难题 人工智能实验 八数码难题 人工智能实验 八数码难题八数码难题简介八数码难题所用到的算法简介代码实现解释运行结果显示代码附件程序可视化 八数码难题简介 八数码问题指的是定义一个3 times 3的格子 xff0c 然
  • idea报错unable to reload maven project

    文章目录 前言一 问题状况二 解决步骤三 卸载maven仓库四 重新安装依赖总结 前言 今天从公司的svn中检出了一个老项目 xff0c 是jQuery 43 spring打造的项目 xff0c emmmm用eclipse编写 xff0c
  • VNC树莓派无法连接

    问题 xff1a 树莓派配置好VNC后 xff0c 第二次通过笔记本远程连接失败 xff0c 报错refused by the computer 解决方法 xff1a 在putty中输入IP地址登录树莓派 xff0c 输入vncserver
  • 经典LCA例题:P4180 [BJWC2010] 严格次小生成树

    Acwing xff1a 严格次小生成树 xff08 求两点间路径上最大边的权值 xff09 模板 洛谷 xff1a 严格次小生成树 求两点间路径上最大边的权值 xff0c 就不能通过前缀和了 xff0c 会丢失信息 每个结点存到其他结点的