P9433 [NAPC-#1] Stage5 - Conveyors

题意简述

给定一个\(N\)个节点的树形结构,每条边有边权,树上有\(k\)个关键点。

接下来有\(q\)次询问,每次询问给定\(x,y\)两点,请计算从\(x\)开始经过这\(k\)个关键点(可以重复经过)再到\(y\)的最短路程。

解题思路

我们可以发现,如果\(x\)与\(y\)都在\(k\)个关键点所形成的最小子图中,那么答案就是这个子图中所有边长度之和\(w\)的两倍,再减去\(x\)到\(y\)的距离,即\(2w-dist(x,y)\)。

为什么呢?因为除了\(x\sim y\)之间的边只需要走\(1\)次,其他边都需要走来回\(2\)次。

那如果\(x,y\)不全在这个子图中呢?那么我们就把\(x,y\)移到里面去,用\(2w-dist(x',y')\)再额外加上移动的距离即可。

为了方便操作,我们把关键点之一当作根节点,这样该子图就一定包含根节点了。

接下来,我们就可以用倍增把\(x,y\)跳到子图中,顺便计算出跳跃的距离,累加到\(2w-dist(x',y')\)中即可。

怎么求跳跃的距离呢?我们用\(dis[u][i]\)表示\(u\)节点往上\(2^i\)层的边权之和,在预处理LCA时计算出来。倍增跳跃时,每跳一次累加一下\(dis\),最终结果就是跳跃距离了。

怎么求\(dist(x,y)\)呢?根据上面的定义,\(dis[u][19]\)足以表示\(u\)到根节点的距离,那么有\(dist(x,y)=dis[x][19]+dis[y][19]-2\times dis[lca(x,y)][19]\)。

(一开始我的思路比较傻,是在倍增求LCA的过程中,每跳一步累加一次\(dis\)。这样显然不如上面优啦)

时间复杂度\(O((n+q)\log N)\)。

\(\texttt{<Code/>}\)

点击查看代码
#include<bits/stdc++.h>
#define N 100010
using namespace std;
int n,k,q,root,w;
struct edge{int to,w;};
vector<edge> G[N];
bool is[N];
int dep[N],fa[N][20],dis[N][20];
void dfs(int u,int father){
dep[u]=dep[father]+1;
fa[u][0]=father;
for(int i=1;i<20;i++)
fa[u][i]=fa[fa[u][i-1]][i-1],
dis[u][i]=dis[u][i-1]+dis[fa[u][i-1]][i-1];
for(auto i:G[u])
if(i.to!=father){
dis[i.to][0]=i.w;
dfs(i.to,u);
if(is[i.to])
is[u]=1,
w+=i.w;
}
}
int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
for(int i=19;i>=0;i--)
if(dep[fa[u][i]]>=dep[v])
u=fa[u][i];
if(u==v) return u;
for(int i=19;i>=0;i--)
if(fa[u][i]!=fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][0];
}
int dist(int u,int v){
return dis[u][19]+dis[v][19]-2*dis[lca(u,v)][19];
}
int jump(int &x){
int ans=0;
for(int i=19;i>=0;i--)
if(fa[x][i]&&!is[fa[x][i]])
ans+=dis[x][i],
x=fa[x][i];
ans+=dis[x][0],x=fa[x][0];
return ans;
}
int main(){
cin>>n>>q>>k;
for(int i=1;i<n;i++){
int u,v,w;
cin>>u>>v>>w;
G[u].push_back({v,w});
G[v].push_back({u,w});
}
for(int i=1;i<=k;i++){
cin>>root;
is[root]=1;
}
dfs(root,0);
w*=2;
while(q--){
int x,y;
cin>>x>>y;
int ans=0;
if(!is[x]) ans+=jump(x);
if(!is[y]) ans+=jump(y);
ans+=w-dist(x,y);
cout<<ans<<"\n";
}
return 0;
}

[题解]P9433 [NAPC-#1] Stage5 - Conveyors的更多相关文章

  1. CCPC、Petrozavodsk Camp、OpenCup 题解汇总

    省赛 \([\text{2021.11.30}]\) 2021 Jilin Collegiate Programming Contest 全部完成. \([\text{2021.12.25}]\) 2 ...

  2. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  3. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  4. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  5. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  6. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  7. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  8. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  9. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  10. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. Antd VUE中table子表同时只展开一个子信息的说明

    前言 在网上搜索了很久,很多方法都不太好用,不过经过整理发现,有一个方式是最简单的,比网路上那些copy粘贴的千篇一律的错来说,其实真正的使用方式很简单 想必大家要实现的效果都是上图这样的 <t ...

  2. 2023人形全能赛竞速机器人mega代码

    mega // @Author : Hcm #include <LobotServoController.h> // 舵机板通信 #include <OneButton.h> ...

  3. FastAPI安全机制:从OAuth2到JWT的魔法通关秘籍

    title: FastAPI安全机制:从OAuth2到JWT的魔法通关秘籍 date: 2025/06/07 08:40:35 updated: 2025/06/07 08:40:35 author: ...

  4. P5995 [PA2014] Lustra

    提供一种极易理解的纯模拟做法. 虽然时空都不是很优秀,但是距离时空超限还绰绰有余.并且没有运用什么深奥的算法与技巧,非常适合算法初学者,并且还留有极大的优化空间. 理解题意,题目要求我们求出是否有工厂 ...

  5. Java IO<4>Java io与装饰器模式

    Java io与装饰器模式 装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包 ...

  6. DotTrace系列:4. 诊断窗体程序变卡之原因分析

    一:背景 1. 讲故事 写这一篇是因为昨天看 dottrace 官方文档时,在评论区看到了一条不友好的评论,截图如下: 虽然语气上带有些许愤怒,但说实话人家也不是无中生有,作为 dottrace 的忠 ...

  7. 常见php正则表达式

    $str=preg_replace("/\s+/", " ", $str); //过滤多余回车 $str=preg_replace("/<[ ] ...

  8. 从零开发Vim-like编辑器(02)探讨编辑器对文本的解析与呈现设计思路

    本文同步发布在我的个人博客:https://zhen.wang 前言 前一篇文章作为开篇,只是介绍了Ratatui的相关使用,引出了一些概念.从本文开始,我们正式进入咱们的Vim-like编辑器的开发 ...

  9. java基础之运算符的优先级

    运算符的优先级(从高到低) 优先 描述 运算符 1 括号 ().[] 2 正负号 +.- 3 自增自减,非 ++.--.! 4 乘除,取余 *./.% 5 加减 +.- 6 移位运算 << ...

  10. C++ 字符函数

    简介 字符函数可以带来处理的方便性. 参考链接 https://blog.csdn.net/weixin_41162823/article/details/80172379