题目链接

题目大意

对于一棵树,求出一个点对于给定的三个点(以下简称 $x$,$y$,$z$ 且可以重复)距离最短。

题解

对于点的距离,不难想到 LCA 处理。而对于本题,则有两种情况。

第一问

  1. 三点中有一为另外两个点的祖先时,所求目标点(以下简称 $v$ )的深度(简称 $d_v$ )一定在三点深度之间。

  2. 三点共同 LCA 为另一点时,$v$ 即为三点的 LCA 。

这两种情况包含了所有形式,所以我们可以通过求出 $\operatorname {LCA(x,y)}$,$\operatorname {LCA(x,z)}$,$\operatorname {LCA(y,z)}$ 后选取最深的点,即所求的 $v$。对于此结论,第二种情况自然不用多说,而第一种情况中显然 $d_x \le d_v \le d_y$($d_x \le d_y \le d_z$),最深的点可以使 $y$ 与 $z$ 到 $v$ 的距离最短,即 $y$ 与 $z$ 不会走相同的边。

第二问

设点 $x$ 到根节点的距离为 $dis_x$,由树的性质得答案为 $dis_x+dis_y+dis_z-dis_{\operatorname{LCA(x,y)}}-dis_{\operatorname{LCA(x,z)}}-dis_{\operatorname{LCA(y,z)}}$。

代码

#include <bits/stdc++.h>
using namespace std;
#define mst(x, y) memset(x, y, sizeof(x))
#define pp pair<int, int>
#define fi first
#define se second
#define mp(x, y) make_pair(x, y) int read(){int x = 0, f = 1;char c = getchar();while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9'){x = 10*x+c-'0';c = getchar();}return f*x;}
void write(int x){if(x < 0){putchar('-');x = -x;}if(x > 9) write(x/10);putchar(x%10 | 0x30);return;}
const int N = 1000005, inf = 0x3f3f3f3f; int n, q, hd[N], ver[N], nxt[N], idx, d[N], f[N][25], ans, mk[N]; void add(int x, int y){
nxt[++idx] = hd[x];
ver[idx] = y;
hd[x] = idx;
}
void bfs(){
queue <int> q;
q.push(1);
mk[1] = 1, d[1] = 1;
while(q.size()){
int t = q.front();
q.pop();
for(int i = hd[t];i;i = nxt[i]){
int y = ver[i];
if(mk[y]) continue;
mk[y] = 1;
d[y] = d[t]+1, f[y][0] = t;
for(int j = 1;j <= 20;j++){
f[y][j] = f[f[y][j-1]][j-1];
}
q.push(y);
}
}
}
int lca(int x, int y){
if(d[x] < d[y]) swap(x, y);
for(int i = 20;i >= 0;i--){
if(d[f[x][i]] >= d[y]) x = f[x][i];
}
if(x == y) return x;
for(int i = 20;i >= 0;i--){
if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
}
return f[x][0];
}
void init(){
n = read(), q = read();
for(int i = 1;i < n;i++){
int x = read(),y = read();
add(x, y);add(y, x);
}
bfs();
}
void solve(){
while(q--){
int x = read(), y = read(), z = read();
int l1 = lca(x, y), l2 = lca(y, z), l3 = lca(x, z);
ans = d[x]+d[y]+d[z]-d[l1]-d[l2]-d[l3];
if(d[l1] >= d[l2] && d[l1] >= d[l3]){
write(l1);putchar(' ');write(ans);puts("");
}
else if(d[l2] >= d[l1] && d[l2] >= d[l3]){
write(l2);putchar(' ');write(ans);puts(""); }
else if(d[l3] >= d[l2] && d[l3] >= d[l1]){
write(l3);putchar(' ');write(ans);puts("");
}
}
} int main(){
init();
solve();
return 0;
}

另外不要忘了双倍经验

P10952 聚会 题解的更多相关文章

  1. toj 4602 松鼠聚会

    题目: 草原上住着一群小松鼠,每个小松鼠都有一个家.时间长了,大家觉得应该聚一聚.但是草原非常大,松鼠们都很头疼应该在谁家聚会才最合理. 每个小松鼠的家可以用一个点x,y表示,两个点的距离定义为:点( ...

  2. 【题解】Luogu P5361 [SDOI2019]热闹又尴尬的聚会

    原题传送门 构造题. 明显p,q都越大越好 我们考虑每次取出度最小的点,加到尴尬聚会的集合中(因为把与它相邻的点全删了,不珂能出现认识的情况),把它自己和与自己相连的点从图上删掉(边也删掉),记下这个 ...

  3. 题解 BZOJ 1037 & Luogu P2592 [ZJOI2008]生日聚会

    BZOJ & Luogu 老师说是背包?并没看出来QAQ 设f[i][j][o][p]表示已经选了i个人,j个男生,男生比女生最多多o个,女生比男生最多多p个时的方案数 两种转移: <= ...

  4. 题解 [BZOJ1832][AHOI2008] 聚会

    题面 解析 首先对于其中的两个点\(x,y\)最近的点显然就是他们的\(lca\)(我们把它设为\(p1\)), 然后考虑第三个点\(z\)与\(p1\)的\(lca,p2\). 有以下几种情况: \ ...

  5. 【简】题解 AWSL090429 【聚会】

    这题直接换根dp 记录在要转移的点的子树中有多少牛 #include<bits/stdc++.h> using namespace std; #define ll long long #d ...

  6. 暑假训练round 3 题解

    今天做题运气出奇的好,除了几处小错误调试之后忘记改掉了……最后还AK了……虽然题目不难,学长也说是福利局,但是对个人的鼓励作用还是挺大的……至此暑假训练就结束了,也算没有遗憾……. 题解如下: Pro ...

  7. BZOJ3170: [Tjoi 2013]松鼠聚会

    3170: [Tjoi 2013]松鼠聚会 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 531  Solved: 249[Submit][Statu ...

  8. BZOJ 3170: [Tjoi 2013]松鼠聚会 切比雪夫距离

    3170: [Tjoi 2013]松鼠聚会 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...

  9. tyvj1161聚会的名单(trie树)

    背景 Background 明天就是candy的生日,candy又会邀请自己的一大堆好友来聚会了!哎!又要累坏飘飘乎居士了!! 描述 Description     明天就是candy的生日.晚上,c ...

  10. [bzoj\lydsy\大视野在线测评]题解(持续更新)

    目录: 一.DP 二.图论 1.最短路 2.强连通分量 三.利用单调性维护 四.贪心 五.数据结构 1.并查集 六.数学 1.计数问题 2.数学分析 七.博弈 八.搜索 /////////////// ...

随机推荐

  1. electon的入口文件 main 指定

    任何 Electron 应用程序的入口都是 main 文件. 这个文件控制了主进程,它运行在一个完整的Node.js环境中,负责控制您应用的生命周期,显示原生界面,执行特殊操作并管理渲染器进程(稍后详 ...

  2. 2024年开源API工具盘点,覆盖API全生命周期

    2024年经济持续低迷,本文整理一些免费的开源工具,旨在帮助企业组织降低工具的支出成本,能用免费的何必用付费的呢(狗头)? 如何高效地管理API的全生命周期--从设计.开发.测试.部署到监控和优化,已 ...

  3. 双指针习题:Kalindrome Array

    Kalindrome Array 题目链接: Kalindrome Array - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题面翻译 对于长度为 \(m\) 的序列 \(b\), ...

  4. 云原生周刊:OpenTofu Registry 获得用户界面和 API|2024.9.9

    开源项目推荐 kubectl trace kubectl trace 是一个 kubectl 插件,它允许你在 Kubernetes 集群中调度执行 bpftrace 程序. Kondense Kon ...

  5. 云原生周刊:Kubernetes v1.30 发布 | 2024.4.22

    开源项目推荐 pv-migrate pv-migrate 是一个 CLI 工具/kubectl 插件,可轻松将一个 Kubernetes 的内容迁移 PersistentVolumeClaim 到另一 ...

  6. 强化学习算法笔记之【DDPG算法】

    强化学习笔记之[DDPG算法] 目录 强化学习笔记之[DDPG算法] 前言: 原论文伪代码 DDPG 中的四个网络 代码核心更新公式 前言: 本文为强化学习笔记第二篇,第一篇讲的是Q-learning ...

  7. CF716B Complete the Word 题解

    CF716B Complete the Word 题解 分析 首先观察数据范围是 \(50000\),可以考虑 \(O(n)\) 暴力. 在字符串中枚举子串开始的位置 \(i\),然后再枚举 \(i\ ...

  8. 定位模组LuatOS快速入门:源UART串口通信

    合宙Air201资产定位模组--是一个集成超低功耗4G通信.语音通话.超低功耗定位.计步.震动.Type-C.充电.放音.录音等功能的超小PCBA. 内部集成高效.简单.可靠的LuatOS语言,旨在帮 ...

  9. fork父子进程执行顺序

    使用一段代码来检查父子进程执行顺序 <?php $str = "hello world!" . PHP_EOL; // 派生一个子进程,子进程会复制主进程中的上下文 // p ...

  10. VUE懒加载的table前端搜索

    // 前端搜索 fliterData() { const search = this.search if (search) { this.blist = this.list.filter(item = ...