简要题意

给出一个 \(N\) 个节点的树和一个长度为 \(M\) 的序列 \(S\)。你需要从 \(1\) 出发,依次经过 \(S\) 中的所有点,求至少需要经过的边数。

\(1 \le N \le 30000\)

思路

首先先给出一个结论:树上两点之间的最短离,等于两点的深度和减去其最近公共祖先的两倍。

证明如下(令 \(d(u)\) 为 \(u\) 的深度,\(r\) 为树根,\(a(u,v)\) 为从 \(u\) 到 \(v\) 的最短距离,\(l(u,v)\) 为 \(u,v\) 的最近公共祖先):

\[\begin{aligned}
&d(u)+d(v)-2d(l(u,v))\\
&=a(r,u)+a(r,v)-a(r,l(u,v))-a(r,l(u,v))\\
&=a(l(u,v),u)+a(r,l(u,v))+a(l(u,v),v)+a(r,l(u,v))-a(r,l(u,v))-a(r,l(u,v))\\
&=a(l(u,v),u)+a(l(u,v),v)\\
&=a(u,v)
\end{aligned}
\]

然后的过程就很简单了,使用树剖(用于求最近公共祖先)和上述结论求出 \(a(1,S_1)+a(S_1,S_2)+\cdots+a(S_{M-1}+S_{M})\) 即可。

时间复杂度 \(O(N+M\log N)\),可以通过本题。

代码

#include <bits/stdc++.h>
using namespace std; const int N = 500005; struct edge {
int nxt, to;
} g[N << 1];
int head[N << 1], ec;
void add(int u, int v) {
g[++ec].nxt = head[u];
g[ec].to = v;
head[u] = ec;
} int root;
int siz[N], son[N], fa[N], top[N], dep[N];
void dfs1(int u, int father, int deep) {
dep[u] = deep;
siz[u] = 1;
fa[u] = father;
for (int i = head[u]; i; i = g[i].nxt) {
int v = g[i].to;
if (v == father) {
continue;
}
dfs1(v, u, deep + 1);
siz[u] += siz[u];
if (siz[v] >= siz[son[u]]) {
son[u] = v;
}
}
} void dfs2(int u, int father, int t) {
top[u] = t;
if (son[u])dfs2(son[u], u, t);
for (int i = head[u]; i; i = g[i].nxt) {
int v = g[i].to;
if (v == father) {
continue;
}
if (v == son[u]) {
continue;
}
dfs2(v, u, v);
}
} int lca(int x, int y) {
int fx = top[x], fy = top[y];
while (fx != fy) {
if (dep[fx] < dep[fy]){
swap(fx, fy);
swap(x, y);
}
x = fa[fx], fx = top[x];
}
if (dep[x] > dep[y]) {
return y;
}
else return x;
} int n,m,s; int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
dfs1(1,0,1);
dfs2(1,0,1);
cin>>m;
int ret=0,u=1,v=0;
while(m--){
cin>>v;
ret+=(dep[u]+dep[v]-2*dep[lca(u,v)]); // 运用结论
u=v;
}
cout<<ret;
return 0;
}

P8855 [POI2002]商务旅行的更多相关文章

  1. 2953: [Poi2002]商务旅行

    2953: [Poi2002]商务旅行 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 8  Solved: 8[Submit][Status] Desc ...

  2. 倍增法-lca codevs 1036 商务旅行

    codevs 1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 某首都城市的商人要经常到各城镇去做生意 ...

  3. C++之路进阶——codevs1036(商务旅行)

    1036 商务旅行 题目描述 Description 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇 ...

  4. 【codevs1036】商务旅行 LCA 倍增

    1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 某首都城市的商人要经常到各城镇去做生意,他们按自己的 ...

  5. poj3728 商务旅行

    [Description]小 T 要经常进行商务旅行,他所在的国家有 N 个城镇,标号为 1,2,3,...,N,这 N 个城镇构成一棵树.每个城镇可以买入和卖出货物,同一城镇买入和卖出的价格一样,小 ...

  6. CodeVs.1036 商务旅行 ( LCA 最近公共祖先 )

    CodeVs.1036 商务旅行 ( LCA 最近公共祖先 ) 题意分析 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从 ...

  7. codevs——1036 商务旅行

    1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 某首都城市的商人要经常 ...

  8. codevs1036商务旅行(LCA)

    1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 某首都城市的商人要经常到各城镇去做 ...

  9. codevs1026商务旅行

    1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 某首都城市的商人要经常到各城镇去做 ...

随机推荐

  1. Linux基础_5_文件管理

    创建 touch 文件名 #创建文件 stat 文件名 #查看文件属性 touch -am 文件名 #更改文件的访问时间及修改时间 删除 rm -rf s/* #递归强制删除s目录下的所有内容(包括文 ...

  2. 算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法

    一.名称 动态规划法应用 二.目的 1.贪婪技术的基本思想: 2.学会运用贪婪技术解决实际设计应用中碰到的问题. 三.要求 1.实现基于贪婪技术思想的Prim算法: 2.实现基于贪婪技术思想的Dijk ...

  3. 在IDEA中使用Maven将SpringBoot项目打成jar包、同时运行打成的jar包(前后端项目分离)

    1.maven教程官网 https://m.runoob.com/maven/ 2.理解Maven的构建生命周期(clean.Package) 3.在项目中使用maven进行打包 4.运行打包好的ja ...

  4. 齐博x1fun实例 鉴于很多人问列表的筛选怎么放到首页、内容页等等地方 贴出方法

    application\common\fun\Field.php 你可以复制一份 也可以直接改 直接改记得加锁 不然升级就覆盖了 我们把   public function list_filter($ ...

  5. PaddleOCR-EAST

    目录 EAST Abstract Train PreProcess Architecture Backbone Neck Head Loss Dice Loss SmoothL1 Loss Infer ...

  6. python关于Django搭建简单博客项目 详解二-setting.py

    这一篇我们来讲解setting.py,具体内容以注释形式写入到下面的setting.py代码中,篇幅所限已把官方所给英文注释删除. 全部源代码和详解请参看http://github.com/Cheng ...

  7. 关于 Vue 中 h() 函数的一些东西

    最近在项目上需要一个信息弹窗,来显示信息.一开始只让它弹出了文字,而且只有一条信息.而给我的需求是多条文字和图片,而后我使用了element ui中的 Notification 通知组件来显示.当然, ...

  8. MQTT+esp32+nodered+springboot 智能家居项目 -- 项目准备

    1.后台系环境:idea  jdk8.0以上  maven   tomcat   spring boot 2.前端环境  nodejs  nodered 3.硬件环境: audrion   esp32 ...

  9. 开源网络协议栈onps诞生记

    小孩没娘,说来话长,一切都要从LwIP说起.大约是06年9月,本人在二姨的坛口发布了一篇小文--<uC/OS-II 平台下的 LwIP 移植笔记>.自此一发不可收拾,开启了一段我与LwIP ...

  10. Linux网络通信(TCP套接字编写,多进程多线程版本)

    预备知识 源IP地址和目的IP地址 IP地址在上一篇博客中也介绍过,它是用来标识网络中不同主机的地址.两台主机进行通信时,发送方需要知道自己往哪一台主机发送,这就需要知道接受方主机的的IP地址,也就是 ...