Kruskal 重构树

最大生成树将部分内容倒置即可

回顾:Kruskal

基本信息

  1. 求解最小生成树
  2. 时间复杂度:\(O(m \log m)\)
  3. 更适合稀疏图

算法思想

  1. 按照边权从小到大排序
  2. 依次枚举每一条边,如果这一条边两侧不连通,则加入这条边

代码

点击查看代码
#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)\)。

主要性质

  1. 重构树是一棵[二叉树];
  2. [子节点的点权]小于[父节点的点权](即大根堆);
  3. 最小生成树上[两点之间的最大边权]等于重构树上[两点之间的最大边权](即为重构树上两点 LCA 的点权)。

结论证明

最小生成树上两点间最大边权等于重构树上两点 LCA 的点权,证明:

  1. 后加入的边权一定小于先加入的边权,所以重构树一定自上到下点权不减;
  2. 两点在最小生成树上的路径的所有边一定都在重构树上两点之间;
  3. 所以两点在最小生成树上之间的最长边权一定是重构树上两点 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;
}

资料来源

Kruskal重构树 学习笔记的更多相关文章

  1. kruskal重构树学习笔记

    \(kruskal\) 重构树学习笔记 前言 \(8102IONCC\) 中考到了,本蒟蒻不会,所以学一下. 前置知识 \(kruskal​\) 求最小(大)生成树,树上求 \(lca​\). 算法详 ...

  2. Kruskal重构树学习笔记+BZOJ3732 Network

    今天学了Kruskal重构树,似乎很有意思的样子~ 先看题面: BZOJ 题目大意:$n$ 个点 $m$ 条无向边的图,$k$ 个询问,每次询问从 $u$ 到 $v$ 的所有路径中,最长的边的最小值. ...

  3. P4197 Peaks [克鲁斯卡尔重构树 + 主席树][克鲁斯卡尔重构树学习笔记]

    Problem 在\(Bytemountains\)有\(n\)座山峰,每座山峰有他的高度\(h_i\) .有些山峰之间有双向道路相连,共\(M\)条路径,每条路径有一个困难值,这个值越大表示越难走, ...

  4. 洛谷P4197 Peaks&&克鲁斯卡尔重构树学习笔记(克鲁斯卡尔重构树+主席树)

    传送门 据说离线做法是主席树上树+启发式合并(然而我并不会) 据说bzoj上有强制在线版本只能用克鲁斯卡尔重构树,那就好好讲一下好了 这里先感谢LadyLex大佬的博客->这里 克鲁斯卡尔重构树 ...

  5. [算法模板]Kruskal重构树

    [算法模板]Kruskal重构树 kruskal重构树是一个很常用的图论算法.主要用于解决u->v所有路径上最长边的最小值,就是找到\(u->v\)的一条路径,使路径上的最长边最小. 图片 ...

  6. 【学习笔记】Kruskal 重构树

    1. 例题引入:BZOJ3551 用一道例题引入:BZOJ3551 题目大意:有 \(N\) 座山峰,每座山峰有他的高度 \(h_i\).有些山峰之间有双向道路相连,共 \(M\) 条路径,每条路径有 ...

  7. [学习笔记]kruskal重构树 && 并查集重构树

    Kruskal 重构树 [您有新的未分配科技点][BZOJ3545&BZOJ3551]克鲁斯卡尔重构树 kruskal是一个性质优秀的算法 加入的边是越来越劣的 科学家们借这个特点尝试搞一点事 ...

  8. 算法学习——kruskal重构树

    kruskal重构树是一个比较冷门的数据结构. 其实可以看做一种最小生成树的表现形式. 在普通的kruskal中,如果一条边连接了在2个不同集合中的点的话,我们将合并这2个点所在集合. 而在krusk ...

  9. [luogu P4197] Peaks 解题报告(在线:kruskal重构树+主席树 离线:主席树+线段树合并)

    题目链接: https://www.luogu.org/problemnew/show/P4197 题目: 在Bytemountains有N座山峰,每座山峰有他的高度$h_i$.有些山峰之间有双向道路 ...

  10. Kruskal重构树——[NOI2018] 归程

    题目链接: UOJ LOJ 感觉 Kruskal 重构树比较简单,就不单独开学习笔记了. Statement 给定一个 \(n\) 点 \(m\) 边的无向连通图,用 \(l,a\) 描述一条边的长度 ...

随机推荐

  1. 关于int**在malloc为二维数组分配空间时候的作用见解

    关于int**在用malloc函数为二维数组分配空间时候 int**   二级指针类型 二维数组的数组名为行指针,写成  arr  =(char**)malloc(n*sizeof(char))时,a ...

  2. Java 新的生态,Solon v2.3.2 发布

    Solon 是什么框架? 一个,Java 新的生态型应用开发框架.它从零开始构建,有自己的标准规范与开放生态(全球第二级别的生态).与其他框架相比,它解决了两个重要的痛点:启动慢,费资源. 解决痛点? ...

  3. jenkins中的坑_CreateProcess error=1392

    环境:windows11,jdk1.8,jenkins_2.346.war 起因 最近在使用jenkins部署项目的时候,填写仓库的url地址时,发现填完后报500这个错误,于是我打开jenkins的 ...

  4. ASP.NET Core 6框架揭秘实例演示[37]:重定向的N种实现方式

    在HTTP的语义中,重定向一般指的是服务端通过返回一个状态码为3XX的响应促使客户端像另一个地址再次发起请求,本章将此称为"客户端重定向".既然有客户端重定向,自然就有服务端重定向 ...

  5. kafka学习笔记02

    kafka拥有与其他几个消息队列同样的本事:   ①缓冲/削峰:控制和优化数据经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况.   应用场景:双十一秒杀活动,将用户消息写入消息队列中,我 ...

  6. 华为云GaussDB亮相2023可信数据库发展大会,荣获三项评测证书!

    摘要:2023可信数据库发展大会上,华为云数据库服务产品部总经理苏光牛围绕华为云GaussDB的产品能力和实践进行了分享 本文分享自华为云社区<华为云GaussDB亮相2023可信数据库发展大会 ...

  7. Net 编译器平台 --- Roslyn

    引言 最近做一个功能想要动态执行C#脚本,就是预先写好代码片段,在程序运行时去执行代码段,比如像这样(以下代码为伪代码): string scriptText = "int a = 1;in ...

  8. playwright(十三) - PyTest基本使用

      我们都知道,在做单元测试框架中有UnitTest和Pytest,前者是Python中自带无需安装,Pytest需要安装,今天我们来讲的就是Pytest,当然如果是做自动化,建议两个都要掌握一下,可 ...

  9. REST API 设计最佳实践:为什么不要在URI中使用动词?

    总的来说,HTTP协议出现以来Web服务也就存在了.但是,自从云计算出现后,才成为实现客户端与服务和数据交互的普遍方法. 作为一名开发者,我很幸运能够在工作中使用一些仍然存在的SOAP服务.但是,我主 ...

  10. HTTP&HTTPS协议

    HTTP协议 1.什么是HTTP 超文本传输协议( HyperText Transfer Protoco,缩写:HTTP)是一种用于分布式.协作式和超媒体信息系统的应用层协议. HTTP(HyperT ...