洛谷p1967货车运输(kruskal重构树)
题解中有很多说最优解是kruskal重构树
所以
抽了个早自习看了看这方面的内容
感觉真的挺好使的
首先对于kruskal算法来说
是基于贪心的思想把边权排序用并查集维护是否是在同一棵树上
对于kruskal重构树来说
按不同边权顺序排序可相应的得到最大边权的最小值 、最小边权的最大值等问题
建树过程:
排好序后, 遍历, 若两条边u, v不在同一并查集内, 那么就新建一个节点, 这个节点的点权就代表u到v的边权, 同时将这三个点都加入同一并查集
需要注意
最后建立出来的可能是森林,也就是并不是所有的点的根都是相同的
此时
可以用一个vis数组来确保所有的点都被遍历过了
1.若按照边权的升序排列
那么最后可以求得最大边权的最小值
感性理解一下
因为最后是要求最小值
所以
建一棵最小生成树
此时最大的边权就是所有别的建树方法中的最小值
2.若按照边权的降序排列
同上
要求最小边权的最大值
最后答案是最大值
那么建一棵最大生成树
关于为什么lca是答案:
感性理解一下
如果我们建的树是最小生成树
那么
显然边权越大深度越深
我们是想按着边权尽量小的走
lca(u, v)是原图u->v节点深度最小的点
所以就是他了
关于此题的代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = ;
int n, m, sum, fa[N], cnt, size[N], top[N], dad[N], head[N], va[N], tot, q, deep[N], vis[N], son[N];
struct Edge{
int from, to, w;
}e[N << ];
struct Node {
int nxt, to, w;
}ee[N];
void add(int x, int y) {
ee[++tot].nxt = head[x];
ee[tot].to = y;
head[x] = tot;
}
bool cmp(Edge x, Edge y) {
return x.w > y.w;
}
int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void dfs(int u, int pa) {
size[u] = ;vis[u] = ;
for(int i = head[u]; i; i = ee[i].nxt) {
int v = ee[i].to;
if(v == pa) continue;
deep[v] = deep[u] + , dad[v] = u;
dfs(v, u);
size[u] += size[v];
if(size[v] > size[son[u]]) son[u] = v;
}
}
void dfs1(int u, int tp) {
top[u] = tp;
if(son[u]) dfs1(son[u], tp);
for(int i = head[u]; i; i = ee[i].nxt) {
int v = ee[i].to;
if(v == dad[u] || v == son[u]) continue;
dfs1(v, v);
}
}
int lca(int x, int y) {
while(top[x] != top[y]) {
if(deep[top[x]] < deep[top[y]]) swap(x, y);
x = dad[top[x]];
}
return deep[x] > deep[y] ? y : x;
}
int main() {
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) fa[i] = i;
cnt = n;
for(int i = ; i <= m; i++)
scanf("%d%d%d", &e[i].from, &e[i].to, &e[i].w);
sort(e + , e + + m, cmp);
for(int i = ; i <= m; i++) {
int fx = find(e[i].from), fy = find(e[i].to);
if(fx != fy) {
va[++cnt] = e[i].w;
fa[fx] = fa[fy] = fa[cnt] = cnt;
add(fx, cnt);add(cnt, fx);
add(fy, cnt);add(cnt, fy);
}
}
for(int i = ; i <= cnt; i++)
if(!vis[i]) {
int f = find(i);
dfs(f, ), dfs1(f, f);
}
/*for(int i = 1; i <= cnt; i++)
printf("%d ", size[i]);*/
scanf("%d", &q);
while(q--) {
scanf("%d%d", &n, &m);
if(find(n) != find(m)) printf("-1\n");
else printf("%d\n", va[lca(n, m)]);
}
return ;
}
谢谢收看, 祝身体健康!
洛谷p1967货车运输(kruskal重构树)的更多相关文章
- Luogu P1967 货车运输(Kruskal重构树)
P1967 货车运输 题面 题目描述 \(A\) 国有 \(n\) 座城市,编号从 \(1\) 到 \(n\) ,城市之间有 \(m\) 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 \ ...
- 洛谷 P1967 货车运输
洛谷 P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在 ...
- 洛谷P3379lca,HDU2586,洛谷P1967货车运输,倍增lca,树上倍增
倍增lca板子洛谷P3379 #include<cstdio> struct E { int to,next; }e[]; ],anc[][],log2n,deep[],n,m,s,ne; ...
- NOIP 2013 提高组 洛谷P1967 货车运输 (Kruskal重构树)
题目: A 国有 nn 座城市,编号从 11 到 nn,城市之间有 mm 条双向道路.每一条道路对车辆都有重量限制,简称限重. 现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情 ...
- 【杂题总汇】NOIP2013(洛谷P1967) 货车运输
[洛谷P1967] 货车运输 重做NOIP提高组ing... +传送门-洛谷P1967+ ◇ 题目(copy from 洛谷) 题目描述 A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道 ...
- [洛谷P4768] [NOI2018]归程 (kruskal重构树模板讲解)
洛谷题目链接:[NOI2018]归程 因为题面复制过来有点炸格式,所以要看题目就点一下链接吧\(qwq\) 题意: 在一张无向图上,每一条边都有一个长度和海拔高度,小\(Y\)的家在\(1\)节点,并 ...
- 洛谷P4768 [NOI2018]归程(Kruskal重构树)
题意 直接看题目吧,不好描述 Sol 考虑暴力做法 首先预处理出从$1$到每个节点的最短路, 对于每次询问,暴力的从这个点BFS,从能走到的点里面取$min$ 考虑如何优化,这里要用到Kruskal重 ...
- 洛谷P4197 Peaks (Kruskal重构树)
读题,只经过困难值小于等于x的路径,容易想到用Kruskal重构树:又要查询第k高的山峰,我们选择用主席树求解. 先做一棵重构树,跑一遍dfs,重构树中每一个非叶子节点对应一段区间,我们开range[ ...
- NOI2018 D1T1 洛谷P4768 归程 (Kruskal重构树)
实际上是一个最短路问题,但加上了海拔这个条件限制,要在海拔<水位线p中找最短路. 这里使用Kruskal重构树,将其按海拔建成小根堆,我们就可以在树中用倍增找出他不得不下车的点:树中节点有两个权 ...
随机推荐
- 面试题 js重写原生函数(以push为例)
先说明一下为什么要写这个,因为最近在面试,面试的时候面试官问了这个问题,当时是真的没有答上来,回来之后自己考虑了一下,现在给大家分享 要求如下: 重写js push函数,使其能够在push的同时打印出 ...
- java中什么是抽象类(abstract)
一.什么是抽象类 由abstract修饰的方法叫抽象方法:由abstract修饰的类叫抽象类.抽象的类无法进行实例化,因为他不是具体存在的类,或者说这样的类还不够完善,不能直接使用new关键字调用其构 ...
- 整理:WPF中应用附加事件制作可以绑定命令的其他事件
原文:整理:WPF中应用附加事件制作可以绑定命令的其他事件 目的:应用附加事件的方式定义可以绑定的事件,如MouseLeftButton.MouseDouble等等 一.定义属于Control的附加事 ...
- spring cloud gateway 深入了解 - Predicate
文章来源 spring cloud gateway 通过谓词(Predicate)来匹配来自用户的请求 为了方便,使用postman测试不同的谓词的效果 路径谓词(Predicate)—— 最简单的谓 ...
- FreePascal - CodeTyphon 如何让编译的程序更小!
CodeTyphon 6.9 在菜单[project]-->[project option]的弹出界面中 选择[compiler option]-->[debugging] 1,去掉“Ge ...
- windows mysql服务器
安装完mysql服务器后,需要启动服务器, 才可提供数据库存储服务.windows上如何启动和关闭mysql服务器呢? 1. 启动 进入mysql的安装目录,如D:\Program Files\mys ...
- centos逻辑卷使用
要求: 1.硬盘格式成物理卷pvpvcreate/dev/sdb/dev/sda 2.创建卷组vgcreatevg1000/dev/sdb1/dev/sdb2#创建卷组”vg1000” 3.增加卷组 ...
- MySQL Table--独立表空间
数据库表空间 独立表空间 在MySQL 5.6 中引入独立表空间的概念,启用独立表空间后,每个表将生成独立的文件来进行存储. 创建表时可以指定表存放的文件路径 ##首选需要确保innodb_file_ ...
- workman即时推送
https://www.workerman.net/web-sender 下载源码解压后运行 start_for_win.bat 如果提示不成功,就把php路径配置到环境变量中去即可 运行后打开浏 ...
- 分析一个UBOOT的方法
1. 编译完成后可以看到在主目录下生成了uboot.bin文件,为了方便分析,使用如下命令将其反汇编:arm-linux-objdump -D -m arm u-boot > u-boot.as ...