1078. 旅游规划 树形dp 图论
W 市的交通规划出现了重大问题,市政府下定决心在全市各大交通路口安排疏导员来疏导密集的车流。
但由于人员不足,W 市市长决定只在最需要安排人员的路口安排人员。
具体来说,W 市的交通网络十分简单,由 n 个交叉路口和 n−1 条街道构成,交叉路口路口编号依次为 0,1,…,n−1 。
任意一条街道连接两个交叉路口,且任意两个交叉路口间都存在一条路径互相连接。
经过长期调查,结果显示,如果一个交叉路口位于 W 市交通网最长路径上,那么这个路口必定拥挤不堪。
所谓最长路径,定义为某条路径 p=(v1,v2,…,vk),路径经过的路口各不相同,且城市中不存在长度大于 k 的路径(因此最长路径可能不唯一)。
因此 W 市市长想知道哪些路口位于城市交通网的最长路径上。
输入格式
第一行包含一个整数 n。
之后 n−1 行每行两个整数 u,v,表示编号为 u 和 v 的路口间存在着一条街道。
输出格式
输出包括若干行,每行包括一个整数——某个位于最长路径上的路口编号。
为了确保解唯一,请将所有最长路径上的路口编号按编号顺序由小到大依次输出。
数据范围
1≤n≤2×105
输入样例:
10
0 1
0 2
0 4
0 6
0 7
1 3
2 5
4 8
6 9
输出样例:
0
1
2
3
4
5
6
8
9
思路
这本身是一个无根树,可以对每个节点都作为根去求,但是这样会超时
任取一个节点作为根,由直径的性质可以知道,直径中必然有一点是最高点,不管这点是不是根节点,因此我们第一遍(自底向上)dfs时求出当前节点向下的两个最大路径时取一下max就可以得到直径的长度,因为总能到达那个最高点,它的两个最大路径都是向下的。
由于需要求出直径上的说所有点,那么就根据:最大的两个路径长度之和等于maxd来判断节点是否在直径上,但是因为我们第一遍dfs都是向下的,除了根节点,其它节点都还要判断向上的情况,因此需要一遍自顶向下的dfs,求出每个节点的向上最大路径值,这也是dp的过程,递推关系:up[j]要么等于上一个节点的d1(j不在u的d1路径上),要么等于d2(j在u的d1路径上)。
和树的重心那题的区别:
树的重心:可以一遍dfs求出向下的节点,同时根据n-sum(子节点),得出向上的值
这题: 一遍dfs只能求出向下的情况,对向上的情况只能通过再用一个dfs用递推来求
代码
import java.util.*;
public class Main{
static int N=200005,M=N*2,n;
static int idx,h[]=new int [N],ne[]=new int [M],e[]=new int [M];
static int d1[]=new int [N],d2[]=new int [N],up[]=new int [N],p1[]=new int [N];
static int maxd=0;
static void add(int a,int b){
e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
static void dfs_d(int u,int f){
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(j!=f){
dfs_d(j,u);
int d=d1[j]+1;
if(d>d1[u]){
d2[u]=d1[u];
d1[u]=d;
p1[u]=j;
}else if(d>d2[u]){
d2[u]=d;
}
}
}
maxd=Math.max(maxd, d1[u]+d2[u]);
}
static void dfs_up(int u,int f){
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(j!=f){
up[j]=up[u]+1;
if(p1[u]==j)up[j]=Math.max(up[j], d2[u]+1);
else up[j]=Math.max(up[j],d1[u]+1);
dfs_up(j,u);
}
}
}
public static void main(String []args){
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
Arrays.fill(h, -1);
for(int i=0;i<n-1;++i){
int a=sc.nextInt();
int b=sc.nextInt();
add(a,b);add(b,a);
}
dfs_d(0,-1);
dfs_up(0,-1);
for(int i=0;i<n;++i){
int t[]={d1[i],d2[i],up[i]};
Arrays.sort(t,0,3);
if(t[1]+t[2]==maxd){
System.out.println(i);
}
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】