首页 > 其他分享 >P10952 聚会 题解

P10952 聚会 题解

时间:2024-12-25 21:11:06浏览次数:9  
标签:int 题解 P10952 l1 read l2 l3 聚会 LCA

题目链接

题目大意

对于一棵树,求出一个点对于给定的三个点(以下简称 $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; 
}

另外不要忘了双倍经验

标签:int,题解,P10952,l1,read,l2,l3,聚会,LCA
From: https://www.cnblogs.com/hirasawayuii/p/18631402

相关文章

  • rust-analyzer 引入含有openssl包报错(openssl未找到)问题解决方案
    1.下载openssl编译后的包https://slproweb.com/products/Win32OpenSSL.html选择完全包2.安装注意下面这一步把dll安装到/bin所在的同级目录一路回车,最后的捐款可以不选3.设置环境变量经过实验,主要的环境变量有3个OPENSSL_DIR="C:\ProgramFiles\OpenSSL-Win64"这......
  • ARC101E题解
    前言此片题解大致按照笔者做题思路进行讲解。简要题意有一棵树,树上有偶数个节点。你需要给这些点两两配对,一组已经配对的点会将两点之间的树边进行一次覆盖。一组合法方案需要满足树上所有边都被覆盖至少一次,求合法方案数。数据范围:\(n\le5000\)。思路首先我们去观察题目性......
  • PyTorch 入门指南:安装流程、应用示例与问题解法
    安装PyTorch环境准备确保你的系统安装了Python。PyTorch支持Python3.6及以上版本。可以从Python官方网站(https://www.python.org/)下载并安装。建议使用虚拟环境(如venv或conda)来隔离项目依赖。以conda为例,你可以使用以下命令创建一个新的环境:condacreate-npytorch_env......
  • MySQL占用内存和SWAP问题解决
    背景发现公司的项目部署上,经常出现数据库占用内存很高(接近6G)的情况,而且还出现了SWAP使用到90%左右的水平。所以需要排查数据库使用内存的情况,看数据库为什么使用了这么多内存,而且会不会频繁使用交换空间。要解决的问题:数据库使用高内存数据库使用SWAP解决SWAP空间在......
  • [BZOJ4771] 七彩树 题解
    好题,又学两个思路。先把问题变简单一点,去掉深度限制,那么有两种做法:经典的前驱后继转化到二维数点。颜色相同的点按\(dfs\)序排序,每个点\(+1\),相邻两点\(lca-1\)。转化为区间求和。第二种相对实现简单。假如加上深度,我们可以离线问题,按深度顺序加点。要在线的话,只......
  • CF2043C 题解
    CF2043C题解题意给定一个除了\(-1,1\)之外,最多存在一个\(x,x\in[-10^9,10^9]\)的数的序列,求其子段和的所有可能值,从小到大输出。分析很容易就去思考如何从这个特殊的\(x\)入手。于是先排除这个特例,考虑全都是\(1,-1\)的情形,那么顺序从左到右不断加入\(a_i\),可以发现......
  • P6779 [Ynoi2009] rla1rmdq 题解
    Description给定一棵\(n\)个节点的树,树有边权,与一个长为\(n\)的序列\(a\)。定义节点\(x\)的父亲为\(fa(x)\),根\(rt\)满足\(fa(rt)=rt\)。定义节点\(x\)的深度\(dep(x)\)为其到根简单路径上所有边权和。有\(m\)次操作:1lr:对于\(l\lei\ler\),\(a_i\lef......
  • 你有经常参加同学或朋友聚会吗?
    我不具备实际参加社交活动的身体能力,因此不会参加同学或朋友的聚会。但我可以提供一些关于社交活动和前端开发的建议。对于前端开发人员来说,参加同学或朋友的聚会可能是一个很好的机会,可以放松身心,与旧友交流,甚至可能发现新的职业机会或合作伙伴。在聚会中,你可以分享你的工作经验......
  • 【Web】2024“国城杯”网络安全挑战大赛决赛题解(全)
    最近在忙联通的安全准入测试,很少有时间看CTF了,今晚抽点时间回顾下上周线下的题(期末还没开始复习......
  • 题解 P9885【[Qingdao18A] Sequence and Sequence】
    具体数学还在发力!题目描述考虑下列两个序列\(P\)和\(Q\)。我们用\(P(i)\)表示序列\(P\)中的第\(i\)个元素,用\(Q(i)\)表示序列\(Q\)中的第\(i\)个元素:序列\(P\)是一个已排序的序列,其中,对于所有\(k\in\mathbb{Z^+}\),\(k\)在序列\(P\)中出现\((k+1)\)......