Kruskal重构树 学习笔记
Kruskal 重构树
最大生成树将部分内容倒置即可
回顾:Kruskal
基本信息
- 求解最小生成树
- 时间复杂度:\(O(m \log m)\)
- 更适合稀疏图
算法思想
- 按照边权从小到大排序
- 依次枚举每一条边,如果这一条边两侧不连通,则加入这条边
代码
点击查看代码
#include <bits/stdc++.h>
#define rr read()
using namespace std;
const int N = 200010;
inline int read()
{
int num = 0, flag = 1;
char ch = getchar();
for (; !isdigit(ch); ch = getchar())
if (ch == '-')
flag = -1;
for (; isdigit(ch); ch = getchar())
num = (num << 3) + (num << 1) + ch - '0';
return num * flag;
}
int f[N];
struct Edge
{
int a, b, w;
bool operator<(const Edge &W) const { return w < W.w; }
} g[N];
int find(int x) { return x == f[x] ? x : find(f[x]); }
int main()
{
int n = rr, m = rr;
int a, b, w;
for (int i = 0; i < m; ++i)
a = rr, b = rr, w = rr, g[i] = {a, b, w};
sort(g, g + m);
for (int i = 1; i <= n; ++i)
f[i] = i;
int res = 0, cnt = 0;
for (int i = 0; i < m; ++i)
{
int a = find(g[i].a), b = find(g[i].b), w = g[i].w;
if (a != b)
f[a] = b, res += w, ++cnt;
}
cnt < n - 1 ? printf("impossible\n") : printf("%d\n", res);
return 0;
}
Kruskal 重构树
算法思想
在构建最小生成树的时候,设现在枚举到了一条要加入最小生成树的边 \((u, v, w)\):
则在 Kruskal 重构树中,构建一个点权为 \(w\) 的虚点,编号为 \(t\),同时连边 \((u, t)\)、\((v, t)\)。
主要性质
- 重构树是一棵[二叉树];
- [子节点的点权]小于[父节点的点权](即大根堆);
- 最小生成树上[两点之间的最大边权]等于重构树上[两点之间的最大边权](即为重构树上两点 LCA 的点权)。
结论证明
最小生成树上两点间最大边权等于重构树上两点 LCA 的点权,证明:
- 后加入的边权一定小于先加入的边权,所以重构树一定自上到下点权不减;
- 两点在最小生成树上的路径的所有边一定都在重构树上两点之间;
- 所以两点在最小生成树上之间的最长边权一定是重构树上两点 LCA 的点权。
如图:
其中红色的点表示虚点,中间的数字表示其点权;白色的点表示原有的点。
代码
#include <bits/stdc++.h>
#define rr read()
using namespace std;
// INPUT GRAPH
const int N = 2e5 + 10;
const int M = 2e5 + 10;
// NEW GRAPH
const int NN = N + M;
const int MM = M + M;
// 4LCA
const int K = 20;
// FAST READ
inline int read()
{
int num = 0, flag = 1;
char ch = getchar();
for (; !isdigit(ch); ch = getchar())
if (ch == '-')
flag = -1;
for (; isdigit(ch); ch = getchar())
num = (num << 3) + (num << 1) + ch - '0';
return num * flag;
}
// NODE, EDGE, QUERY
int n, m, q;
// INPUT GRAPH
struct e
{
int u, v, w;
bool operator<(const e &t) const { return w < t.w; }
} g[M];
// UNOIN
int f[NN];
int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }
// NEW GRAPH
int d[NN], cnt;
int h[NN], e[MM], ne[MM], idx;
// 4LCA
int depth[NN];
int up[NN][K];
// ADD TO NEW GRAPH
inline void _add(int u, int v)
{
e[idx] = v;
ne[idx] = h[u];
h[u] = idx++;
}
void add(int a, int b, int w)
{
d[++cnt] = w;
f[a] = f[b] = cnt;
_add(a, cnt), _add(cnt, a);
_add(b, cnt), _add(cnt, b);
}
// LCA INIT
void init(int u, int fa)
{
depth[u] = depth[fa] + 1;
for (int i = 1; i < K; ++i)
up[u][i] = up[up[u][i - 1]][i - 1];
for (int i = h[u]; i != -1; i = ne[i])
{
int v = e[i];
if (v == fa)
continue;
up[v][0] = u, init(v, u);
}
}
// KRUSKAL
int kruskal()
{
sort(g + 1, g + 1 + m);
for (int i = 1; i <= n * 2; ++i)
f[i] = i;
cnt = n;
memset(h, -1, sizeof h);
int res = 0;
for (int i = 1; i <= m; ++i)
{
int u = find(g[i].u), v = find(g[i].v), &w = g[i].w;
if (u == v)
continue;
res += w, add(u, v, w);
}
init(cnt, 0);
return res;
}
// LCA
int lca(int x, int y)
{
if (depth[x] < depth[y])
swap(x, y);
for (int i = K - 1; i >= 0; --i)
{
if (depth[up[x][i]] >= depth[y])
x = up[x][i];
if (x == y)
return x;
}
for (int i = K - 1; i >= 0; --i)
if (up[x][i] != up[y][i])
x = up[x][i], y = up[y][i];
return up[x][0];
}
int main()
{
n = rr, m = rr;
int a, b, w;
for (int i = 1; i <= m; ++i)
a = rr, b = rr, w = rr, g[i] = {a, b, w};
q = rr;
int res = kruskal();
while (q--)
printf("%d\n", d[lca(rr, rr)]);
return 0;
}
资料来源
- https://www.luogu.com.cn/blog/lizbaka/kruskal-chong-gou-shu
- https://blog.csdn.net/m0_61735576/article/details/124804973
Kruskal重构树 学习笔记的更多相关文章
- kruskal重构树学习笔记
\(kruskal\) 重构树学习笔记 前言 \(8102IONCC\) 中考到了,本蒟蒻不会,所以学一下. 前置知识 \(kruskal\) 求最小(大)生成树,树上求 \(lca\). 算法详 ...
- Kruskal重构树学习笔记+BZOJ3732 Network
今天学了Kruskal重构树,似乎很有意思的样子~ 先看题面: BZOJ 题目大意:$n$ 个点 $m$ 条无向边的图,$k$ 个询问,每次询问从 $u$ 到 $v$ 的所有路径中,最长的边的最小值. ...
- P4197 Peaks [克鲁斯卡尔重构树 + 主席树][克鲁斯卡尔重构树学习笔记]
Problem 在\(Bytemountains\)有\(n\)座山峰,每座山峰有他的高度\(h_i\) .有些山峰之间有双向道路相连,共\(M\)条路径,每条路径有一个困难值,这个值越大表示越难走, ...
- 洛谷P4197 Peaks&&克鲁斯卡尔重构树学习笔记(克鲁斯卡尔重构树+主席树)
传送门 据说离线做法是主席树上树+启发式合并(然而我并不会) 据说bzoj上有强制在线版本只能用克鲁斯卡尔重构树,那就好好讲一下好了 这里先感谢LadyLex大佬的博客->这里 克鲁斯卡尔重构树 ...
- [算法模板]Kruskal重构树
[算法模板]Kruskal重构树 kruskal重构树是一个很常用的图论算法.主要用于解决u->v所有路径上最长边的最小值,就是找到\(u->v\)的一条路径,使路径上的最长边最小. 图片 ...
- 【学习笔记】Kruskal 重构树
1. 例题引入:BZOJ3551 用一道例题引入:BZOJ3551 题目大意:有 \(N\) 座山峰,每座山峰有他的高度 \(h_i\).有些山峰之间有双向道路相连,共 \(M\) 条路径,每条路径有 ...
- [学习笔记]kruskal重构树 && 并查集重构树
Kruskal 重构树 [您有新的未分配科技点][BZOJ3545&BZOJ3551]克鲁斯卡尔重构树 kruskal是一个性质优秀的算法 加入的边是越来越劣的 科学家们借这个特点尝试搞一点事 ...
- 算法学习——kruskal重构树
kruskal重构树是一个比较冷门的数据结构. 其实可以看做一种最小生成树的表现形式. 在普通的kruskal中,如果一条边连接了在2个不同集合中的点的话,我们将合并这2个点所在集合. 而在krusk ...
- [luogu P4197] Peaks 解题报告(在线:kruskal重构树+主席树 离线:主席树+线段树合并)
题目链接: https://www.luogu.org/problemnew/show/P4197 题目: 在Bytemountains有N座山峰,每座山峰有他的高度$h_i$.有些山峰之间有双向道路 ...
- Kruskal重构树——[NOI2018] 归程
题目链接: UOJ LOJ 感觉 Kruskal 重构树比较简单,就不单独开学习笔记了. Statement 给定一个 \(n\) 点 \(m\) 边的无向连通图,用 \(l,a\) 描述一条边的长度 ...
随机推荐
- 关于int**在malloc为二维数组分配空间时候的作用见解
关于int**在用malloc函数为二维数组分配空间时候 int** 二级指针类型 二维数组的数组名为行指针,写成 arr =(char**)malloc(n*sizeof(char))时,a ...
- Java 新的生态,Solon v2.3.2 发布
Solon 是什么框架? 一个,Java 新的生态型应用开发框架.它从零开始构建,有自己的标准规范与开放生态(全球第二级别的生态).与其他框架相比,它解决了两个重要的痛点:启动慢,费资源. 解决痛点? ...
- jenkins中的坑_CreateProcess error=1392
环境:windows11,jdk1.8,jenkins_2.346.war 起因 最近在使用jenkins部署项目的时候,填写仓库的url地址时,发现填完后报500这个错误,于是我打开jenkins的 ...
- ASP.NET Core 6框架揭秘实例演示[37]:重定向的N种实现方式
在HTTP的语义中,重定向一般指的是服务端通过返回一个状态码为3XX的响应促使客户端像另一个地址再次发起请求,本章将此称为"客户端重定向".既然有客户端重定向,自然就有服务端重定向 ...
- kafka学习笔记02
kafka拥有与其他几个消息队列同样的本事: ①缓冲/削峰:控制和优化数据经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况. 应用场景:双十一秒杀活动,将用户消息写入消息队列中,我 ...
- 华为云GaussDB亮相2023可信数据库发展大会,荣获三项评测证书!
摘要:2023可信数据库发展大会上,华为云数据库服务产品部总经理苏光牛围绕华为云GaussDB的产品能力和实践进行了分享 本文分享自华为云社区<华为云GaussDB亮相2023可信数据库发展大会 ...
- Net 编译器平台 --- Roslyn
引言 最近做一个功能想要动态执行C#脚本,就是预先写好代码片段,在程序运行时去执行代码段,比如像这样(以下代码为伪代码): string scriptText = "int a = 1;in ...
- playwright(十三) - PyTest基本使用
我们都知道,在做单元测试框架中有UnitTest和Pytest,前者是Python中自带无需安装,Pytest需要安装,今天我们来讲的就是Pytest,当然如果是做自动化,建议两个都要掌握一下,可 ...
- REST API 设计最佳实践:为什么不要在URI中使用动词?
总的来说,HTTP协议出现以来Web服务也就存在了.但是,自从云计算出现后,才成为实现客户端与服务和数据交互的普遍方法. 作为一名开发者,我很幸运能够在工作中使用一些仍然存在的SOAP服务.但是,我主 ...
- HTTP&HTTPS协议
HTTP协议 1.什么是HTTP 超文本传输协议( HyperText Transfer Protoco,缩写:HTTP)是一种用于分布式.协作式和超媒体信息系统的应用层协议. HTTP(HyperT ...