HDU2196 Computer【树形DP】

题目链接:HDU2196 Computer【树形DP】

题意:给你一个树,求出所有节点在树中能到达的点的最远距离;

分析:dp[i][0],表示顶点为i的子树的,距顶点i的最长距离;dp[i][1],表示Tree(i的父节点)-Tree(i)的最长距离+i跟i的父节点距离;dp[i][0]通过dfs1可以很快求出;dp[i][1]可以通过父节点转移来,要维护一个最长mx1和经过的子节点v1,次大mx2和子节点v2,更新时如果v是v1,那么只能从mx2转移,否则就是从mx1转移;

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int maxn=1e5+7;
bool vis[maxn];
int dp[maxn][2];
struct node{int v,w;};
vector<node> g[maxn];
int n;
int dfs1(int u)
{
    vis[u]=1;dp[u][0]=0;
    for(auto i:g[u]) if(!vis[i.v]) dp[u][0]=max(dp[u][0],dfs1(i.v)+i.w);
    return dp[u][0];
}
void dfs2(int u)
{
    vis[u]=1;
    int mx1=0,mx2=0,v1,v2;
    for(auto i:g[u])
    {
        if(vis[i.v]) continue;
        int kk=dp[i.v][0]+i.w;
        if(kk>mx1) {mx2=mx1;v2=v1;mx1=kk;v1=i.v;}
        else if(kk==mx1 || kk>mx2) mx2=kk,v2=i.v;
    }
    if(u!=1)
    {
        int kk=dp[u][1],v=-1;
        if(kk>mx1) {mx2=mx1;v2=v1;mx1=kk;v1=v;}
        else if(kk==mx1 || kk>mx2) mx2=kk,v2=v;
    }
    for(auto i:g[u])
    {
        if(vis[i.v]) continue;
        if(i.v==v1) dp[i.v][1]=mx2+i.w;
        else dp[i.v][1]=mx1+i.w;
        dfs2(i.v);
    }
}
int main()
{
    while(~scanf("%d",&n) && n)
    {
        for(int i=0;i<n;i++) g[i].clear();
        for(int u=2;u<=n;u++)
        {
            int v,w;scanf("%d%d",&v,&w);
            g[u].pb({v,w});g[v].pb({u,w});
        }
        memset(dp,-1,sizeof(dp));
        memset(vis,0,sizeof(vis));
        dfs1(1);
        memset(vis,0,sizeof(vis));
        dfs2(1);
        for(int i=1;i<=n;i++) printf("%d\n",max(dp[i][0],dp[i][1]));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43813163/article/details/102595073