前言

使用算法:堆优化 \(prim\) , \(LCA\) 。

题意

共有 \(n\) 个点,有 \(m\) 条边来连接这些点,每条边有权值。有 \(q\) 条类似于 \(u\) \(v\) 询问,求一条从 \(u\) 到 \(v\) 的路径使得路径上的最小权值最大,求这个最大值。若不存在从 \(u\) 到 \(v\) 的路径,则输出 \(-1\) 。

思路

先求该图的最大生成树,因为需要使得该路径上的最小值最大,而这条路径就是最小生成树的中两点的简单路径(最大生成树尽量取最大的边)。

故而,查询时的路径确定了,那么现在就是求这条路径的最小值了。

树上的距离操作离不开 \(LCA\) 。

假设查询 \(2\) 和 \(4\) 之间的距离最小值。那么它们之间的简单路径为 \(2->1->3->4\) ,可以分为两段:\(s->lca\) 和 \(lca->t\) 。这就是两条链,可以使用倍增求解。两条链的最小值一起来求最小值即可。

查询两个点是否在路径很简单,就是判断他们是否在一个连通块,直接在处理 \(prim\) 时一起求解即可。

C++代码

#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f
#define Swap(a, b) (a ^= b ^= a ^= b)
#define Min(a, b) ((a) < (b) ? (a) : (b))
void Quick_Read(int &N) {
N = 0;
int op = 1;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-')
op = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
N = (N << 1) + (N << 3) + (c ^ 48);
c = getchar();
}
N *= op;
}
const int MAXN = 1e4 + 5;
const int MAXM = 40;
struct Node {
int to, dist;
Node() {}
Node(int T, int D) {
to = T;
dist = D;
}
friend bool operator < (Node x, Node y) {
return x.dist < y.dist;
}
};
int fa[MAXN][MAXM], minn[MAXN][MAXM];
int de[MAXN];
vector<Node> v[MAXN];
priority_queue<Node> q;
bool vis[MAXN];
int dis[MAXN], belong[MAXN];
int ans, tot;
int n, m, t;
int LCA(int x, int y) {
if(de[x] < de[y])
Swap(x, y);
for(int i = 30; i >= 0; i--)
if(de[x] - (1 << i) >= de[y])
x = fa[x][i];
if(x == y)
return x;
for(int i = 30; i >= 0; i--) {
if(fa[x][i] != fa[y][i]) {
x = fa[x][i];
y = fa[y][i];
}
}
return fa[x][0];
}
int Climb(int x, int y) {
int res = INF;
for(int i = 30; i >= 0; i--)
if(de[x] - (1 << i) >= de[y]) {
res = Min(res, minn[x][i]);
x = fa[x][i];
}
return res;
}
void Prim(int s) {
tot++;
dis[s] = 0;
q.push(Node(s, 0));
fa[s][0] = s;
while(!q.empty()) {
int now = q.top().to, adddist = q.top().dist;
q.pop();
if(vis[now])
continue;
belong[now] = tot;
ans += adddist;
vis[now] = true;
int SIZ = v[now].size();
for(int i = 0; i < SIZ; i++) {
int next = v[now][i].to;
if(v[now][i].dist > dis[next] && !vis[next]) {
fa[next][0] = now;
de[next] = de[now] + 1;
minn[next][0] = v[now][i].dist;
dis[next] = v[now][i].dist;
q.push(Node(next, dis[next]));
}
}
}
}
void Query() {
int A, B;
Quick_Read(t);
for(int i = 1; i <= t; i++) {
Quick_Read(A);
Quick_Read(B);
if(belong[A] != belong[B])
printf("-1\n");
else {
int lca = LCA(A, B);
int ans1 = Climb(A, lca);
int ans2 = Climb(B, lca);
printf("%d\n", Min(ans1, ans2));
}
}
}
void Build() {
memset(dis, 128, sizeof(dis));
for(int i = 1; i <= n; i++)
if(!vis[i])
Prim(i);
for(int j = 1; j < 31; j++)
for(int i = 1; i <= n; i++) {
fa[i][j] = fa[fa[i][j - 1]][j - 1];
minn[i][j] = Min(minn[fa[i][j - 1]][j - 1], minn[i][j - 1]);
}
}
void Read() {
int A, B, C;
Quick_Read(n);
Quick_Read(m);
for(int i = 1; i <= m; i++) {
Quick_Read(A);
Quick_Read(B);
Quick_Read(C);
v[A].push_back(Node(B, C));
v[B].push_back(Node(A, C));
}
}
int main() {
Read();
Build();
Query();
return 0;
}

[NOIP2013 提高组] 货车运输的更多相关文章

  1. [NOIP2013提高组]货车运输

    题目:洛谷P1967.Vijos P1843.codevs3287. 题目大意:有n个城市m条道路,每条道路有一个限重,规定货车运货不能超过限重.有一些询问,问你两个城市之间一次最多能运多少重的货(可 ...

  2. [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路

    [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路 题目大意: 对于长度为\(n(n\le10^5)\)的非负数列\(A\),每次可以选取一个区间\(-1\).问将数列清零至少需要 ...

  3. [NOIP2013 提高组] 华容道 P1979 洛谷

    [NOIP2013 提高组] 华容道 P1979 洛谷 强烈推荐,更好的阅读体验 经典题目:spfa+bfs+转化 题目大意: 给出一个01网格图,和点坐标x,y空格坐标a,b,目标位置tx,ty要求 ...

  4. 【NOIP2013提高组】货车运输

    货车运输  (truck.cpp/c/pas) [问题描述]  A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有q辆货车在运输货物,司机们想知道每辆 ...

  5. 洛谷P1967 [NOIP2013提高组Day1T2]货车运输

    P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过 ...

  6. [NOIP2013提高组] CODEVS 3287 火车运输(MST+LCA)

    一开始觉得是网络流..仔细一看应该是最短路,再看数据范围..呵呵不会写...这道题是最大生成树+最近公共祖先.第一次写..表示各种乱.. 因为要求运输货物质量最大,所以路径一定是在最大生成树上的.然后 ...

  7. NOIP2013 提高组 Day1

    https://www.luogu.org/problem/lists?name=&orderitem=pid&tag=83%7C30 期望得分:100+100+100=300 实际得 ...

  8. 【NOIP2013提高组T3】加分二叉树

    题目描述 设一个n个节点的二叉树tree的中序遍历为(1,2,3,…,n),其中数字1,2,3,…,n为节点编号.每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都 ...

  9. noip2013 提高组

    T1 转圈游戏 题目传送门 果不其然 第一题还是模拟题 一波快速幂解决问题 #include<cstdio> #include<cstring> #include<alg ...

随机推荐

  1. mfc c++优化

    1.不住求精度时,尽量使用单精度浮点型2.使用32位数据类型3.使用有符号和无符号整型: 前提:无需考虑正负时 double x; int i; x = i; 使用有符号:unsigned int i ...

  2. JavaScript原型链及其污染

    JavaScript原型链及其污染 一.什么是原型链? 1.JavaScript中,我们如果要define一个类,需要以define"构造函数"的方式来define: functi ...

  3. MongoDB 分片集群配置

    本文测试环境为 CentOS 7 和 MongoDB 最新版 (4.0.12) 使用 root 操作 (实际操作中使用非 root 账户启动报错) 零.服务器分配 服务器 102 服务器 103 服务 ...

  4. Java中正则表达式的使用(常用的方法)

    这两天回想了一下正则表达式的使用,顺便就总结了一下java的javascript中使用正则表达式的用法,需要看javascript中使用正则的朋友可以看我的另一篇总结,下面我就简单的介绍一下java中 ...

  5. 老猿学5G专栏文章目录

    ☞ ░ 前往老猿Python博文目录 ░ 一.3GPP规范文档及其他推荐阅读博文 老猿学5G扫盲贴:3GPP规范文档命名规则及同系列文档阅读指南 老猿学5G扫盲贴:3GPP规范中部分与计费相关的规范序 ...

  6. 老猿Python重难点知识博文汇总

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 除了相关教程外,老猿在学习过程中还写了大量的学习随笔,内容比较杂,文章内容也参差不齐,为了方便,老猿 ...

  7. 第11.19节 Python 中正则表达式的扩展功能:前视断言和前视取反

    一. 引言 在<第11.16节 Python正则元字符"()"(小括号)与组(group)匹配模式>中老猿介绍了组匹配模式的命名组功能及引用组功能,这两者都是组模式的扩 ...

  8. PyQt(Python+Qt)学习随笔:QAbstractItemView的tabKeyNavigation属性

    老猿Python博文目录 老猿Python博客地址 tabKeyNavigation属性为bool类型,用于控制视图中是否启用tab键和backtab(shift+tab)进行数据项之间的导航切换. ...

  9. PyQt(Python+Qt)学习随笔:布局控件layout的layoutSizeConstraint属性不起作用的问题解决办法

    在<PyQt(Python+Qt)学习随笔:布局控件layout的layoutSizeConstraint属性>中介绍layout的layoutSizeConstraint属性后,反复测试 ...

  10. PyQt(Python+Qt)学习随笔:布局控件layoutSpacing属性

    在Qt Designer中布局控件有4个,分别是Vertical Layout(垂直布局).Horizontal Layout(水平布局).Grid Layout(网格布局).Form Layout( ...