AcWing算法提高课 树形dp 树的中心

AcWing 1073. 树的中心 

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;

vector<int> adj[10010];
vector<int> w[10010];
int p[10010];
int wp[10010];
LL dis1[10010];
LL dis2[10010];
int next1[10010];
int next2[10010];
LL udis[10010];
LL res=1e15;
int DFS(int node,int parent)
{
    p[node]=parent;

    LL d1=0,d2=0;
    LL nxt1=-1,nxt2=-1;
    for(int i=0;i<adj[node].size();i++)
    {
        int nxt=adj[node][i];
        if(nxt!=p[node])
        {
            
            LL d=w[node][i]+DFS(nxt,node);
            if(d>=d1) d2=d1,nxt2=nxt1,d1=d,nxt1=nxt;
            else if(d>d2) d2=d,nxt2=nxt;
        }
        else
        {
            wp[node]=w[node][i];
        }
    }
    dis1[node]=d1;
    dis2[node]=d2;
    next1[node]=nxt1;
    next2[node]=nxt2;

    return d1;

}
void DFS(int node)
{
    if(p[node]<1)
    {
        udis[node]=0;
        res=min(res,dis1[node]);
    }
    else
    {
        udis[node]=wp[node];
        if(next1[p[node]]==node)
        {
            udis[node]+=max(udis[p[node]],dis2[p[node]]);
        }
        else
        {
            udis[node]+=max(udis[p[node]],dis1[p[node]]);
        }

        res=min(res,max(dis1[node],udis[node]));
    }
    for(int i=0;i<adj[node].size();i++)
    {
        int nxt=adj[node][i];
        if(nxt!=p[node])
            DFS(nxt);
    }
    
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        adj[a].push_back(b);
        w[a].push_back(c);
        adj[b].push_back(a);
        w[b].push_back(c);
    }
    DFS(1,-1);
    DFS(1);
    cout<<res<<endl;
    
}
View Code

 

求树的中心需要,求节点到其他节点的最远距离。

最远距离分成两类:

第一类是向子节点(下)走的最远距离,

第二类是向父节点(上)走的最远距离。

可以进行两次dfs,

第一次求出向下走的最大值和次大值并记录(记录距离和节点),子->父,和求直径时dfs方法一样。

第二次则可以,更新节点向上走的最大值,父->子,

其中,当子节点向上走的最远距离为,到父节点的权重+max(父节点向上走的最远距离,父节点向下走(除了当前点)的最远距离)。

 

然后可以遍历,求出某节点到其他节点的最远距离,即为向上和向下走的最大值。

 

 

 

posted @ 2022-06-16 13:02  80k  阅读(27)  评论(0编辑  收藏  举报