P10952 聚会 题解
题目链接
题目大意
对于一棵树,求出一个点对于给定的三个点(以下简称 $x$,$y$,$z$ 且可以重复)距离最短。
题解
对于点的距离,不难想到 LCA 处理。而对于本题,则有两种情况。
第一问
三点中有一为另外两个点的祖先时,所求目标点(以下简称 $v$ )的深度(简称 $d_v$ )一定在三点深度之间。
三点共同 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 聚会 题解的更多相关文章
- toj 4602 松鼠聚会
题目: 草原上住着一群小松鼠,每个小松鼠都有一个家.时间长了,大家觉得应该聚一聚.但是草原非常大,松鼠们都很头疼应该在谁家聚会才最合理. 每个小松鼠的家可以用一个点x,y表示,两个点的距离定义为:点( ...
- 【题解】Luogu P5361 [SDOI2019]热闹又尴尬的聚会
原题传送门 构造题. 明显p,q都越大越好 我们考虑每次取出度最小的点,加到尴尬聚会的集合中(因为把与它相邻的点全删了,不珂能出现认识的情况),把它自己和与自己相连的点从图上删掉(边也删掉),记下这个 ...
- 题解 BZOJ 1037 & Luogu P2592 [ZJOI2008]生日聚会
BZOJ & Luogu 老师说是背包?并没看出来QAQ 设f[i][j][o][p]表示已经选了i个人,j个男生,男生比女生最多多o个,女生比男生最多多p个时的方案数 两种转移: <= ...
- 题解 [BZOJ1832][AHOI2008] 聚会
题面 解析 首先对于其中的两个点\(x,y\)最近的点显然就是他们的\(lca\)(我们把它设为\(p1\)), 然后考虑第三个点\(z\)与\(p1\)的\(lca,p2\). 有以下几种情况: \ ...
- 【简】题解 AWSL090429 【聚会】
这题直接换根dp 记录在要转移的点的子树中有多少牛 #include<bits/stdc++.h> using namespace std; #define ll long long #d ...
- 暑假训练round 3 题解
今天做题运气出奇的好,除了几处小错误调试之后忘记改掉了……最后还AK了……虽然题目不难,学长也说是福利局,但是对个人的鼓励作用还是挺大的……至此暑假训练就结束了,也算没有遗憾……. 题解如下: Pro ...
- BZOJ3170: [Tjoi 2013]松鼠聚会
3170: [Tjoi 2013]松鼠聚会 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 531 Solved: 249[Submit][Statu ...
- BZOJ 3170: [Tjoi 2013]松鼠聚会 切比雪夫距离
3170: [Tjoi 2013]松鼠聚会 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...
- tyvj1161聚会的名单(trie树)
背景 Background 明天就是candy的生日,candy又会邀请自己的一大堆好友来聚会了!哎!又要累坏飘飘乎居士了!! 描述 Description 明天就是candy的生日.晚上,c ...
- [bzoj\lydsy\大视野在线测评]题解(持续更新)
目录: 一.DP 二.图论 1.最短路 2.强连通分量 三.利用单调性维护 四.贪心 五.数据结构 1.并查集 六.数学 1.计数问题 2.数学分析 七.博弈 八.搜索 /////////////// ...
随机推荐
- 11-react使用props.children 处理父子组件之间的传值
// props.children 组件传值 import { Component } from "react" import reactDom from "react- ...
- 9.24 csp(没学会的网络流)
T1.商品 因为边界 l , r 是线性移动的,所以答案可以线性改变,直接用set维护连续段(小于l的和大于r的)的个数,并维护ans即可. 因为set的一个小错误调了两个小时,代码打成了一坨,结果最 ...
- DC-1内网靶机入门
DC-1 1.安装dc-1 靶机 2.内网扫描 查看主机IP ip a ifconfig nmap扫描全网段 nmap -A -p- -v 192.168.27.0/24 -A 选项会执行操作系统探测 ...
- Linux(Redhat 7.6)安装PG(Postgresql 9.6.0)
Linux(Redhat 7.6)安装PG(Postgresql 9.6.0) 1. 摘要 需要在Linux上安装postgres数据库,指定安装目录,简单测试各种配置.安装包下载地址: //源码 h ...
- Linux利用scp命令上传下载文件
scp是secure copy的简写,用于在 Linux 下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器. scp传输是加密的,可能会稍微影响一下速度.当你服务 ...
- TXT文本Log日志分割工具(附工具链接)
前言 相信大家也会像我一样,生产出现了问题,拿下来的日志,用文本编辑器打开直接卡死,甚至说非常卡,查起来非常麻烦且费时间 当当当当 ~~~~~~ 又小,免费非安装的TXT文件分割器就此诞生 链接地址: ...
- 4-11.3 C++中的显式类转换
目录 static_cast 1.用来改变基本类型:一般是高精度转低精度 2.恢复void* 指针类型 const_cast 用来去除底层const(low-level const) reinterp ...
- (Redis基础教程之十二) 如何解决Redis中的故障
介绍 Redis是一个开源的内存中键值数据存储.它带有几个命令,可以帮助您进行故障排除和调试.由于Redis具有内存中的键值存储的性质,因此其中许多命令都集中在内存管理上,但是还有一些其他命令对于概述 ...
- Java Study For Seven Day( 面向对象三)
继承 class Person { String name; int age; } class Student extends Person { void study() { System.out.p ...
- 一、FreeRTOS学习笔记-基础知识
一基础知识 1.任务调度(调度器) 调度器就是使用相关的调度算法来决定当前需要执行的哪个任务 FreeRTOS三种任务调度方式: 1.抢占式调度:主要是针对优先级不同的任务,每个任务都有一个优先级,优 ...