简要题意

给出一个 \(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. Educational Codeforces Round 122 (Rated for Div. 2)/codeforces1633

    CodeForces1633 Div. 7 解析: 题目大意 给定 \(t\) 组数据.每组数据给定一个数 \(n\)(\(10\le n\le 999\)). 每次操作可以修改 \(n\) 任意一位 ...

  2. LcdTools如何编写MIPI指令(初始化代码)

    在LcdTools帮助文档中查看MIPI读写指令描述,如下图 编写LCM初始化代码就是配置LCM Driver IC寄存器值,一般只需用MipiWrite()指令写参数即可:下面介绍MipiWrite ...

  3. SQL中事务以及全局变量的使用

    事务的定义 简单的说,事务处理可以用来维护数据库的完整性,保证一批SQL语句要么全执行,要么全部不执行 事务的特性 原子性  一致性  持久性  隔离性        注:一元九个 事务的使用 sel ...

  4. VUE v-model 语法糖

    v-model 语法糖 描述:弹出利用v-model语法糖 父组件 子组件

  5. 前端学习笔记--HTML5

    网页的优点(客户端为网页)(B/S)模式 开发成本低) 不需要安装 无需更新 跨平台(最重要)可以有效的减小开发成本 传统的为C/S模式,开发成本高 前端工程师负责写网页的源代码,而浏览器负责把网页渲 ...

  6. c++ 模板 指针类型偏特化

    一步步来,先简单点. 目标:我们要实现一个模板类,例化后,可以通过get_val获取到值,通过get_ptr获取到指针.具体什么意思结合例子来看看吧. 例子: struct A{ int data; ...

  7. 再来一次,新技术搞定老业务「GitHub 热点速览 v.22.44」

    上上周 Next.js 新版本火了一把,这不本周热点趋势就有了一个 Next.js 13 新特性构建的网站,虽然它只是个实验性项目.同样可以搞定一些业务的还有 lama-cleaner,不过它并不是个 ...

  8. JS数据结构与算法-概述

    JS数据结构与算法概述 数据结构: 计算机存储, 组织数据的方式, 就像锅碗瓢盆 算法: 一系列解决问题的清晰指令, 就像食谱 两者关系: 程序 = 数据结构 + 算法 邂逅数据结构与算法 什么是数据 ...

  9. java学习之IO流

    java io流有四大家族分别是: 1.InputStream(字节输入流) 2.OutputStream(字节输入出流)3.Reader(字符输入流)4.Writer(字符输出流)四个类都是抽象类 ...

  10. MySQL数据库的性能分析 ---图书《软件性能测试分析与调优实践之路》-手稿节选

    1  .MySQL数据库的性能监控 1.1.如何查看MySQL数据库的连接数 连接数是指用户已经创建多少个连接,也就是MySQL中通过执行 SHOW  PROCESSLIST命令输出结果中运行着的线程 ...