1073. 树的中心(树形dp)
Posted CCSU_Cola
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1073. 树的中心(树形dp)相关的知识,希望对你有一定的参考价值。
给定一棵树,树中包含 nn 个结点(编号1~n)和 n−1 条无向边,每条边都有一个权值。
请你在树中找到一个点,使得该点到树中其他结点的最远距离最近。
思路:既然要找到一个点距离最远的点的距离最近,那么如果以任意点为根节点去dfs,那么某个点距离最远的点一定会被其下面最远的点更新,这个可以通过树形dp直接能到达的最深的深度即可,但是它同时也会被其父节点能到达的最远距离更新,于是我们每个点需要维护一个最大值和次小值和该点的最大值是哪个儿子节点更新的,然后再跑一次dfs,即可得到某个节点的父亲节点能到的最大值为多少,直接判断其父亲能到的最大值是不是自身,如果是,那么只有可能被自己的父节点的次小值加上到父节点的距离更新。否则就是该节点的父节点的最大值加上到父节点的距离更新。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=10010,INF=1e9;
struct tt{
ll to,x,val;
};
tt e[maxn<<1];
int d1[maxn],d2[maxn];
int n,idx,h[maxn];
int p1[maxn],up[maxn];
void add(int a,int b,int c){
e[idx].x=b,e[idx].val=c,e[idx].to=h[a],h[a]=idx++;
}
void dfs(int x,int fa){
d1[x]=d2[x]=-INF;
for(int i=h[x];i!=-1;i=e[i].to){
int j=e[i].x;
if(j==fa)continue;
dfs(j,x);
ll len=d1[j]+e[i].val;
if(len>d1[x]){
d2[x]=d1[x];
d1[x]=len;
p1[x]=j;
}
else if(len>d2[x]){
d2[x]=len;
}
}
if(d1[x]==-INF)d1[x]=d2[x]=0;
}
void dfss(int x,int fa){
for(int i=h[x];i!=-1;i=e[i].to){
int j=e[i].x;
if(j==fa)continue;
if(p1[x]==j)up[j]=max(up[x],d2[x])+e[i].val;
else up[j]=max(up[x],d1[x])+e[i].val;
dfss(j,x);
}
}
int main(){
memset(h,-1,sizeof h);
scanf("%d",&n);
int a,b,c;
for(int i=1;i<n;i++){
scanf("%d%d%d",&a,&b,&c);
add(a,b,c),add(b,a,c);
}
dfs(1,-1);
dfss(1,-1);
int res=INF;
for(int i=1;i<=n;i++){
res=min(res,max(d1[i],up[i]));
}
printf("%d\\n",res);
}
以上是关于1073. 树的中心(树形dp)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 348E 树的中心点的性质 / 树形DP / 点分治