树形DPhdu2196

给你n个电脑,每两台电脑之间有权值,给出n-1条边,问每台电脑距离其它电脑最远的距离。
这道题有两种解法的代码。最开始的解法我是先随便选个点跑dfs,得到当前节点距离最远距离的点j,然后从j开始跑更新子节点从父亲节点来的最大值,然后再得到j节点距离最远的点k,然后从k再开始跑更新子节点从父亲节点来的最大值。最后输出即可,可总感觉会有bug但太弱菜无法证明。之后是发现菊苣们都是对当前节点考虑,只需要更新从子节点来的最大距离,和从父亲节点过来的最大距离。但是需要添加个次大值,因为更新从父亲节点来的最大值时,之前更新的从子节点来的最大值后父亲节点的最大值的状态可能是从当前节点过去的,因为当前节点也是父亲节点的子节点,那么不能选,需选择次大值,即另一个父亲节点过来的次大值。两份代码分别如下。

#include
#include
#include
#include
#define INF 1e9
using namespace std;

struct node
{
    int to,next,w;
}s[11000*2];

int head[11000],cnt,dp[11000],visit[11000];

void init()
{
    memset(head,-1,sizeof(head));
    memset(visit,0,sizeof(visit));
    memset(dp,0,sizeof(dp));
    cnt=0;
}

void add(int a,int b,int w)
{
    s[cnt].to=b;
    s[cnt].w=w;
    s[cnt].next=head[a];
    head[a]=cnt++;
    s[cnt].to=a;
    s[cnt].w=w;
    s[cnt].next=head[b];
    head[b]=cnt++;
}

void dfs(int u,int fa)
{
  //    printf("%d %d %d\n",u,dp[u],sum);
    for(int i=head[u];i+1;i=s[i].next)
    {
        if(fa!=s[i].to)
        {
            dp[s[i].to]=max(dp[u]+s[i].w,dp[s[i].to]);
            dfs(s[i].to,u);
        }
    }
//    printf("!%d ~",u);
}

int main()
{
    int n,i,j;
    while(~scanf("%d",&n))
    {
        int a,b;
        init();
        for(i=2;i<=n;i++)
        {
            scanf("%d %d",&a,&b);
            add(i,a,b);
        }
        dfs(1,-1);
        cnt=-1;
        int k=0;
        for(i=1;i<=n;i++)
        {
            if(dp[i]>cnt)
            {
                cnt=dp[i];
                k=i;
            }
        }
        memset(dp,0,sizeof(dp));
        dfs(k,-1);
        cnt=k=-1;
        for(i=1;i<=n;i++)
        {
            if(dp[i]>cnt)
            {
                cnt=dp[i];
                k=i;
            }
            visit[i]=dp[i];
        }
        memset(dp,0,sizeof(dp));
        dfs(k,-1);
        for(i=1;i<=n;i++)
        printf("%d\n",max(visit[i],dp[i]));
    }
}
#include
#include
#include
#include
using namespace std;
vector<int>Edge[10010],W[10010];
int dis[100010],dp[100010][2];
int maxn[10010],maxid[10010],smaxn[10010],smaxid[10010];

void dfs1(int u,int fa)
{
    maxn[u]=0;
    smaxn[u]=0;
    for(int i=0;iint v=Edge[u][i];
        int w=W[u][i];
        if(v==fa) continue;
        dfs1(v,u);
        if(smaxn[u]if(smaxn[u]>maxn[u])
            {
                swap(smaxn[u],maxn[u]);
                swap(smaxid[u],maxid[u]);
            }
        }
    }
}

void dfs2(int u,int fa)
{
    for(int i=0;iint v=Edge[u][i];
        int w=W[u][i];
        if(v==fa) continue;
        if(v==maxid[u])
        {
            if(smaxn[u]+w>smaxn[v])
            {
                smaxn[v]=smaxn[u]+w;
                smaxid[v]=u;
                if(smaxn[v]>maxn[v])
                {
                    swap(smaxn[v],maxn[v]);
                    swap(smaxid[v],maxid[v]);
                }
            }
        }
        else
        {
            if(maxn[u]+w>smaxn[v])
            {
                smaxn[v]=maxn[u]+w;
                smaxid[v]=u;
                if(smaxn[v]>maxn[v])
                {
                    swap(smaxn[v],maxn[v]);
                    swap(smaxid[v],maxid[v]);
                }
            }
        }
        dfs2(v,u);
    }
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int a,b;
        for(int i=1;i<=n;i++)
        {
            Edge[i].clear();
            W[i].clear();
        }
        for(int i=2;i<=n;i++)
        {
            scanf("%d %d",&a,&b);
            Edge[i].push_back(a);
            W[i].push_back(b);
            Edge[a].push_back(i);
            W[a].push_back(b);
        }
        dfs1(1,-1);
        dfs2(1,-1);
        for(int i=1;i<=n;i++)
        printf("%d\n",maxn[i]);
    }
}

你可能感兴趣的:(树形dp,dp)