题意

Link

给出一张$n$个点的无向图,每次询问两点之间边权最大值最小的路径

$n \leqslant 15000, m \leqslant 30000, k \leqslant 20000$

Sol

很显然答案一定在最小生成树上,但是此题还有一个更为玄学的做法—Kruskal重构树

它是在Kruskal算法上改进而来的。

算法流程:

  1. 对于此题来说,将边权从小到大排序
  2. 用并查集维护两点的联通性,若祖先不相同,那么新建一个节点,权值为边权。左右儿子分别为两个点

这样建出来的树,我们称之为Kruskal重构树

它有许多美妙的性质

  • 是一颗二叉树
  • 两点的LCA的点权为原图中最大值最小的路径上的最大值
  • 任意点的权值大于左右儿子的权值,是一个大根堆

对于此题的样例来说,建出来的图大概长这样

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 1e5 + , INF = 1e9, B = ;
inline int read() {
char c = getchar(); int x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
int fa[MAXN], f[MAXN][], ch[MAXN][], cnt, val[MAXN], deep[MAXN];
int N, M, K;
struct Edge {
int u, v, w;
bool operator < (const Edge &rhs) const {
return w < rhs.w;
}
}E[MAXN];
int head[MAXN], num = ;
inline void AddEdge(int x, int y, int z) {
E[++num] = (Edge){x, y, z};
}
int find(int x) {
if(fa[x] == x) return fa[x];
else return fa[x] = find(fa[x]);
}
void Kruskal() {
sort(E + , E + num + );
int tot = ;
for(int i = ; i <= M; i++) {
int x = E[i].u, y = E[i].v;
int fx = find(x), fy = find(y);
if(fx == fy) continue;
ch[++cnt][] = fx, ch[cnt][] = fy;
fa[fa[x]] = fa[fa[y]] = f[fa[x]][] = f[fa[y]][] = cnt;
val[cnt] = E[i].w; }
}
void dfs(int x) {
if(!ch[x][] && !ch[x][]) return ;
deep[ch[x][]] = deep[ch[x][]] = deep[x] + ;
dfs(ch[x][]); dfs(ch[x][]);
}
int LCA(int x, int y) {
if(deep[x] < deep[y]) swap(x, y);
for(int i = B; i >= ; i--)
if(deep[f[x][i]] >= deep[y])
x = f[x][i];
if(x == y) return x;
for(int i = B; i >= ; i--)
if(f[x][i] != f[y][i])
x = f[x][i], y = f[y][i];
return f[x][];
}
main() {
//freopen("a.in", "r", stdin);
cnt = N = read(); M = read(); K = read();
for(int i = ; i <= N << ; i++) fa[i] = i;
for(int i = ; i <= M; i++) {
int x = read(), y = read(), z = read();
AddEdge(x, y, z);
}
Kruskal();
deep[cnt] = ; dfs(cnt);
for(int i = ; i <= B; i++)
for(int j = ; j <= * N; j++)
f[j][i] = f[f[j][i - ]][i - ];
while(K--) {
int x = read(), y = read();
// printf("%d\", LCA(x, y));
printf("%d\n", val[LCA(x, y)]);
}
return ;
}

BZOJ3732: Network(Kruskal重构树)的更多相关文章

  1. [bzoj 3732] Network (Kruskal重构树)

    kruskal重构树 Description 给你N个点的无向图 (1 <= N <= 15,000),记为:1-N. 图中有M条边 (1 <= M <= 30,000) ,第 ...

  2. 【BZOJ 3732】 Network Kruskal重构树+倍增LCA

    Kruskal重构树裸题, Sunshine互测的A题就是Kruskal重构树,我通过互测了解到了这个神奇的东西... 理解起来应该没什么难度吧,但是我的Peaks连WA,,, 省选估计要滚粗了TwT ...

  3. BZOJ3732 (Kruskal重构树)

    Kruskal重构树上\(x\)和\(v\)的\(lca\)的权值即为它们最长路最小值 #include <cstdio> #include <iostream> #inclu ...

  4. BZOJ 3732: Network Kruskal 重构树

    模板题,练练手~ Code: #include <cstdio> #include <algorithm> #define N 80000 #define setIO(s) f ...

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

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

  6. BZOJ3732 Network(Kruskal重构树)

    Kruskal重构树的模板题. 给你N个点的无向图 (1 <= N <= 15,000),记为:1-N.图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: ...

  7. 【BZOJ】3732: Network【Kruskal重构树】

    3732: Network Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2812  Solved: 1363[Submit][Status][Dis ...

  8. BZOJ 3732 Network 【模板】kruskal重构树

    [题解] 首先,我们可以发现,A到B的所有路径中,最长边的最小值一定在最小生成树上.我们用Kruskal最小生成树时,假设有两个点集U,V,若加入一条边w(u,v)使U,V联通,那么w就是U中每个点到 ...

  9. Kruskal重构树+LCA || BZOJ 3732: Network

    题面:https://www.lydsy.com/JudgeOnline/problem.php?id=3732 题解:Kruskal重构树板子 代码: #include<cstdio> ...

随机推荐

  1. Codeforces Round #528 Solution

    A. Right-Left Cipher Solved. 注意长度的奇偶 #include <bits/stdc++.h> using namespace std; string s; i ...

  2. 2018 Multi-University Training Contest 9 Solution

    A - Rikka with Nash Equilibrium 题意:构造一个$n * m$的矩阵,使得$[1, n * m]$ 中每个数只出现一次,并且纳什均衡只出现一次. 思路:从大到小的放置,每 ...

  3. Codeforces Round #275 (Div. 2) 题解

    A 题: 说的是在(LR) 之间找出ab互质 bc 互质 ac 不互质的 3个数 数据量小直接暴力 #include <iostream> #include <cstdio> ...

  4. 20145307陈俊达《网络对抗》Exp3 免杀原理与实践

    20145307陈俊达<网络对抗>Exp3 免杀原理与实践 基础问题回答 杀软是如何检测出恶意代码的? 恶意代码中一般会有一段有较明显特征的代码也就是特征码,如果杀毒软件检测到有程序包含的 ...

  5. ifconfig源码分析之与内核交互数据

    <ifconfig源码分析之与内核交互数据>本文档的Copyleft归rosetta所有,使用GPL发布,可以自由拷贝.转载,转载时请保持文档的完整性.参考资料:<Linux设备驱动 ...

  6. codevs 2216 行星序列 线段树+延迟标记(BZOJ 1798)

    2216 行星序列  时间限制: 2 s  空间限制: 256000 KB     题目描述 Description “神州“载人飞船的发射成功让小可可非常激动,他立志长大后要成为一名宇航员假期一始, ...

  7. Windows服务程序_测试01

    1. #include <stdio.h> #include <Windows.h> #include <tchar.h> #include <process ...

  8. Solaris 11 让 ls 的输出 带上颜色

    Solaris 默认的ls , 是不会显示 文件和文件夹的颜色的. 我们可以利用 gnu 的 ls 命令. 修改:~/.bashrc alias ls='/usr/gnu/bin/ls --color ...

  9. HDU - 4804 Campus Design 轮廓线dp

    题意:一个nm的矩阵被12的骨牌和11的骨牌完全覆盖,11的骨牌只能放c-d次,矩阵中有障碍物 题解:dp[i][j][k]表示到了第i行,第j个状态,放过k个11的骨牌,当前位有障碍物时只有一种转移 ...

  10. java反射教程

    什么是反射,为什么它是有用的,以及如何使用它? 1.什么是反射? “反射通常是JVM中运行的程序需要检测和修改运行时程序的行为的一种能力.”这个概念通常与内省(Introspection)混淆.以下是 ...