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\) 描述一条边的长度 ...
随机推荐
- 今天在内部 Galaxy 分析平台操作探针引物设计小工具程序,调用 Ensembl API 获取相关序列和信息时,发现官网 MySQL server 异常,报告问题后当天晚上就收到了回复,并且修......
本文分享自微信公众号 - 生信科技爱好者(bioitee).如有侵权,请联系 support@oschina.cn 删除.本文参与"OSC源创计划",欢迎正在阅读的你也加入,一起分 ...
- 如何取消Blazor Server烦人的重新连接?
如何取消Blazor Server烦人的重新连接? 相信很多Blazor的用户在开发内部系统上基本上都选择速度更快,加载更快的Blazor Server模式. 但是Blazor Server由于是Si ...
- httpx的两个坑(httpx.ReadTimeout; SSL: CERTIFICATE_VERIFY_FAILED)
关于python异步网络请求库httpx的两个坑 其一:httpx.ReadTimeout 实测发现,网络不稳定的情况下,极其容易出现该错误. 相对于requests库, httpx库是有默认的超时时 ...
- Eclipse Alt + / 无提示
步骤 一: Widows - Preference - Java - Editor - Content Assist - Advanced 勾选 Java Proposals 二: 在这个位置 点的后 ...
- 前端使用CSS固定表头
* { margin: 0; padding: 0 } .tableFixedTop { padding: 20px } .tableFixedTop table { border: 1px soli ...
- 在映客的虚拟KTV里唱了一首“爱你”
如果你突然打了个喷嚏 那一定就是我在想你 如果半夜被手机吵醒 啊~那是你的虚拟 KTV 在响起 2022 年 5 月 18 日,映客 App 上线了业内首个元宇宙 K 歌玩法「全景 K 歌」,给用 ...
- 图像处理评价指标_划分系数Vpc划分熵Vpe
划分系数划分熵 评价指标划分系数Vpc和划分熵Vpe能够反映分割矩阵的模糊程度,Vpc数值越大,分割矩阵的模糊性越小,分割效果越好:Vpe数值越小,像素分类越准确,分割效果越好. (1)划分系数Vpc ...
- shell: logging + readlog
logging #!/bin/bash # a small tool for logging sommething # # 1. read your input # 2. save to logs f ...
- 2021-11-30 wpf的mvvm绑定2
主页页面代码 <Grid> <TextBox x:Name="First" Width="80" Height="20" ...
- Blazor前后端框架Known-V1.2.8
V1.2.8 Known是基于C#和Blazor开发的前后端分离快速开发框架,开箱即用,跨平台,一处代码,多处运行. Gitee: https://gitee.com/known/Known Gith ...