专栏文章
SP20775
SP20775题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minh9r3w
- 此快照首次捕获于
- 2025/12/02 02:23 3 个月前
- 此快照最后确认于
- 2025/12/02 02:23 3 个月前
题面
有一个树, 次询问,每次求以 为根的子树中的最长路径长度!(话说这题为什么没人写啊
题解
树形 dp。
定义 是以 为根的子树中的最长路径长度(就是题目中要求的)。
对 进行分讨:
- 这条路径不经过 ,那就是在其子节点的子树上取最长路径。
- 这条路径经过 ,那就是在子树中取两条路径,这两条路径都以 的子节点为路径端点,然后把这两条路径通过 串起来。
令 是 的子节点。
第一种情况:。
第二种情况比较难处理,但发现以 为路径端点的最长路径也可以树形 dp 求出来,设这个值为 ,那么 。
则对于第二种情况,取子节点中 的最大值和次大值,加起来再加上 即可(就是加上连到 的这两条边)。
代码
CPP#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,r,q;
int head[N],to[2*N],nxt[2*N],idx;
int f[N][5];
void add(int x,int y) {
nxt[++idx]=head[x],head[x]=idx,to[idx]=y;
return;
}
void dfs(int x,int fa) {
int mx=0;
for(int i=head[x];i;i=nxt[i]) {
int y=to[i];
if(y!=fa) {
dfs(y,x);
f[x][0]=max(f[x][0],f[y][0]);
if(f[y][1]+1>f[x][1]) {
mx=f[x][1];
f[x][1]=f[y][1]+1;
}
else if(f[y][1]+1>mx) mx=f[y][1]+1;
}
}
f[x][0]=max(f[x][0],mx+f[x][1]);
}
int main() {
scanf("%d",&n);
for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
scanf("%d",&r);
dfs(r,0);
scanf("%d",&q);
while(q--) {
int x;
scanf("%d",&x);
printf("%d\n",f[x][0]);
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...