专栏文章

题解:AT_abc428_e [ABC428E] Farthest Vertex

AT_abc428_e题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minkh853
此快照首次捕获于
2025/12/02 03:53
3 个月前
此快照最后确认于
2025/12/02 03:53
3 个月前
查看原文

题意

给定一棵大小为 nn 的树,对于树上的每一个节点求与节点距离最远的节点编号,有多个距离相等则返回较大的那个。

解法

考虑树上动态规划,设 fu,0/1f_{u,0/1} 为在以 uu 为根的子树中,离节点 uu 最远的节点的距离和编号,转移方程如下:
  • vvuu 的子节点,若 fv,0+1>fu,0f_{v,0}+1>f_{u,0}fv,0+1=fu,0f_{v,0}+1=f_{u,0}fv,1>fu,1f_{v,1}>f_{u,1},则 fu,0fv,0+1f_{u,0}\gets f_{v,0}+1fu,1fv,1f_{u,1}\gets f_{v,1}
然后考虑换根即可。

代码

CPP
#include<bits/stdc++.h>
#define mkp make_pair
using namespace std;
const int N=5e5+5;
vector<int>edge[N];
void build(int u,int v){edge[u].push_back(v);}
pair<int,int>f[N];
void get_f(int u,int fa)
{
    f[u]={0,u};
    for(int v:edge[u])
    {
        if(v==fa)continue;
        get_f(v,u);
        pair<int,int>tmp={f[v].first+1,f[v].second};
        if(f[u]<tmp)f[u]=tmp;
    }
}
int ans[N];
void get_ans(int u,int fa)
{
    f[u]={0,u};
    pair<int,int>maxn;
    for(int v:edge[u])
    {
        pair<int,int>tmp={f[v].first+1,f[v].second};
        if(tmp>f[u])maxn=f[u],f[u]=tmp;
        else if(tmp>maxn)maxn=tmp;
    }
    ans[u]=f[u].second;
    for(int v:edge[u])
    {
        if(v==fa)continue;
        pair<int,int>t=f[u],tmp={f[v].first+1,f[v].second};
        if(f[u]==tmp)f[u]=maxn;
        get_ans(v,u);
        f[u]=t;
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin>>n;
    for(int i=1,u,v;i<n;i++)cin>>u>>v,build(u,v),build(v,u);
    get_f(1,0),get_ans(1,0);
    for(int i=1;i<=n;i++)cout<<ans[i]<<'\n';
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...