当前位置: 首页 > article >正文

蓝桥杯真题 - 景区导游 - 题解

题目链接:https://www.lanqiao.cn/problems/3516/learning/

个人评价:难度 4 星(满星:5)
前置知识:LCA


整体思路

  • 假设能快速算出任意两个节点 u , v u,v u,v 之间的距离,就可以先算一遍所有 A i A_i Ai A i + 1 A_{i+1} Ai+1 之间的距离总和,记为 d i s S u m = ∑ i = 1 i = K − 1 d i s A i , A i + 1 disSum=\sum_{i=1}^{i=K-1} dis_{A_i,A_{i+1}} disSum=i=1i=K1disAi,Ai+1,然后考虑跳过每一个 A i   ( 2 ≤ i ≤ K − 1 ) A_i~(2 \leq i \leq K-1) Ai (2iK1) 节点的情况:把 d i s S u m disSum disSum 减去 ( d i s A i − 1 , A i + d i s A i , A i + 1 ) (dis_{A_{i-1},A_i} + dis_{A_i,A_{i+1}}) (disAi1,Ai+disAi,Ai+1),再加上 d i s A i − 1 , A i + 1 dis_{A_{i-1},A_{i+1}} disAi1,Ai+1 就是跳过节点 A i A_i Ai 的结果(当 i = 1 i=1 i=1 i = K i=K i=K 时直接把 d i s S u m disSum disSum 分别减去 d i s A 1 , A 2 dis_{A_1,A_2} disA1,A2 d i s A K − 1 , A K dis_{A_{K-1},A_K} disAK1,AK 即可);
  • 先用一个 dfs 跑出所有节点 u u u 到根节点的距离 d i s u , r o o t dis_{u,root} disu,root,然后任意两个节点之间的距离,就是它们到根节点之间的距离总和减去两倍的它们最近公共祖先到根节点的距离,假设用 LCA 求出最近公共祖先节点为 f f f,则任意两点间距离为

d i s u , v = d i s u , r o o t + d i s v , r o o t − 2 × d i s f , r o o t dis_{u,v}=dis_{u,root}+dis_{v,root}-2\times dis_{f,root} disu,v=disu,root+disv,root2×disf,root

过题代码

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int Log = 20;
const int maxn = 100000 + 100;
struct Node {
    int pos;
    LL dis;
    Node() {}
    Node(int pos, LL dis) : pos(pos), dis(dis) {}
};

int n, k, u, v, t, idCnt;
int st[maxn][Log];
LL disSum;
vector<Node> G[maxn];
int id[maxn], a[maxn];
LL dis[maxn], disPre[maxn];

void dfs(int root, int fa) {
    id[root] = ++idCnt;
    st[root][0] = fa;
    for(int j = 1; j < Log; ++j) {
        st[root][j] = st[st[root][j - 1]][j - 1];
    }
    for (Node &node: G[root]) {
        int pos = node.pos;
        if (pos != fa) {
            dis[pos] = dis[root] + node.dis;
            dfs(pos, root);
        }
    }
}

int lca(int x, int y) {
    if(x == y) {
        return x;
    }
    if(id[x] > id[y]) {
        swap(x, y);
    }
    for(int i = Log - 1; i >= 0; --i) {
        if(id[st[y][i]] > id[x]) {
            y = st[y][i];
        }
    }
    return st[y][0];
}

int main() {
#ifdef ExRoc
    freopen("test.txt", "r", stdin);
#endif // ExRoc
    ios::sync_with_stdio(false);

    cin >> n >> k;
    for (int i = 1; i < n; ++i) {
        cin >> u >> v >> t;
        G[u].push_back(Node(v, t));
        G[v].push_back(Node(u, t));
    }
    dfs(1, 1);
    for (int i = 1; i <= k; ++i) {
        cin >> a[i];
    }
    for (int i = 2; i <= k; ++i) {
        int f = lca(a[i], a[i - 1]);
        disPre[i] = dis[a[i]] + dis[a[i - 1]] - 2 * dis[f];
        disSum += disPre[i];
    }
    cout << disSum - disPre[2] << " ";
    for (int i = 1; i + 2 <= k; ++i) {
        int f = lca(a[i], a[i + 2]);
        cout << disSum - disPre[i + 1] - disPre[i + 2] + dis[a[i]] + dis[a[i + 2]] - 2 * dis[f] << " ";
    }
    cout << disSum - disPre[k] << endl;

    return 0;
}

http://www.kler.cn/a/522098.html

相关文章:

  • 实验七 带函数查询和综合查询(2)
  • git中有关old mode 100644、new mode 10075的问题解决小结
  • LTV预估 | 深度学习PLTV之开山鼻祖ZILN
  • 文件上传2
  • 关于WPF中ComboBox文本查询功能
  • Vue 3 + TypeScript 实现父子组件协同工作案例解析
  • 新中地GIS开发特训营:引领地理空间技术革命
  • golang通过AutoMigrate方法自动创建table详解
  • 【蓝桥杯】43692.青蛙跳杯子
  • 【深度学习基础】多层感知机 | 实战Kaggle比赛:预测房价
  • 【JavaScript笔记】01- 原型及原型链(面试高频内容)
  • cherry USB 键盘分析
  • 算法题(49):反转链表II
  • Python3 OS模块中的文件/目录方法说明十二
  • DeepSeek R1:中国AI黑马的崛起与挑战
  • AI Agent的安全实践:权限控制与数据保护
  • 1. Java-MarkDown文件创建-工具类
  • 系统思维和升维思维以及它们对项目经理重要性
  • 定时任务Spring Task双向数据传输WebSocket
  • 第05章 14 绘制人脸部的PolyData并使用小圆锥体来展现法线
  • Go反射指南
  • 爱的魔力转圈圈,基于carsim与simulink模拟仰望u8原地调头
  • DeepSeek-R1 是否才是 “Open” AI?
  • YOLOv11改进,YOLOv11检测头融合DynamicHead,并添加小目标检测层(四头检测),适合目标检测、分割等任务
  • 航空客户价值的数据挖掘与分析(numpy+pandas+matplotlib+scikit-learn)
  • 基于STM32的循迹小车设计与实现