HDU 3534:Tree 树形DP

Tree

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3534

题意:

有一棵树,问树上的最长路径以及最长路径的数量。

题解:

比较简单但是有点麻烦的一个题。设两个数组:

      dp[i][0]代表以 i 为根节点的子树上的最长路径(i 点可以是端点也可以是中间点),dp[i][1]则代表该路径的数量

      dis[i][0]代表以 i 为根节点的子树上的单程最长路径(i 点只能是端点而不可以是中间点),dis[i][1]则代表该路径的数量

那么问题就很简单了,dp[i]将可能由两种方式得到,①是由dp[child[i]]得到,②是max(dis[child[i]]+距离(i,child[i]))

      ①直接枚举环找最大的dp[child[i]][0]即可

      ②记录dis[child][0]的最大值和次大值以及它们的数量,最后做简单处理即可

经验证题目中的N不会大于1W,答案不会超过int32,且边权均大于0

代码

 
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
const int N=10005;
int mmax(int x,int y)
{
    return x>y?x:y;
}
struct node
{
    int to,cost;
    node(int x=0,int y=0)
    {
        to=x,cost=y;
    }
};
vector<node>q[N];
bool mark[N];
int dp[N][2],dis[N][2];
void Dfs_TreeDp(int id)
{
    mark[id]=true;
    int mdis=-1,sdis=-1,mnum=0,snum=0,ss,mm;
    for(int i=0;i<q[id].size();++i)
    {
        int v=q[id][i].to;
        int w=q[id][i].cost;
        if(mark[v])continue;
        Dfs_TreeDp(v);
        
        if(dp[v][0]>dp[id][0])
        {
            dp[id][0]=dp[v][0];
            dp[id][1]=dp[v][1];
        }
        else if(dp[v][0]==dp[id][0])
        dp[id][1]+=dp[v][1]; 
        
        if(dis[v][0]+w>mdis)
        {
            sdis=mdis,snum=mnum,snum=ss;
            mdis=dis[v][0]+w,mnum=1;
            mm=0,ss=dis[v][1];
        }
        else if(dis[v][0]+w==mdis)
        mnum++,mm=mm+ss*dis[v][1],ss+=dis[v][1];
        else if(dis[v][0]+w>sdis)
        {
            sdis=dis[v][0]+w;
            snum=dis[v][1];
        }
        else if(dis[v][0]+w==sdis)
        snum+=dis[v][1];
    }
    if(mdis!=-1)
    {        dis[id][0]=mdis,dis[id][1]=ss;
        if(mnum>1)
        {
            if(mdis*2>dp[id][0])
            {
                dp[id][0]=mdis*2;
                dp[id][1]=mm;
            }
            else if(mdis*2==dp[id][0])
            {
                dp[id][0]=mdis*2;
                dp[id][1]+=mm;
            }
        }
        else if(sdis!=-1)
        {
            if(mdis+sdis>dp[id][0])
            {
                dp[id][0]=mdis+sdis;
                dp[id][1]=snum*ss;
            }
            else if(mdis+sdis==dp[id][0])
            {
                dp[id][0]=mdis+sdis;
                dp[id][1]+=snum*ss;
            }
        }
        else
        {
            if(mdis>dp[id][0])
            {
                dp[id][0]=mdis;
                dp[id][1]=ss;
            }
            else if(mdis==dp[id][0])
            {
                dp[id][0]=mdis;
                dp[id][1]+=ss;
            }
        }
    }
    if(dp[id][0]==0)
    {
        dp[id][1]=1;
        dis[id][1]=1;
    }
}
void solve()
{
    int n,a,b,c;
    while(~scanf("%d",&n))
    {
        memset(dp,0,sizeof(dp));
        memset(dis,0,sizeof(dis));
        for(int i=1;i<=n;++i)
        q[i].clear();
        memset(mark,false,sizeof(mark));
        if(n>10000)while(1);
        for(int i=1;i<n;++i)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(c<=0||c*n>1000000000)while(1);
            q[a].push_back(node(b,c));
            q[b].push_back(node(a,c));
        }
        Dfs_TreeDp(1);
        printf("%d %d
",dp[1][0],dp[1][1]);
    }
    
}
int main()
{
    solve();
    return 0;
}

  

原文地址:https://www.cnblogs.com/kiuhghcsc/p/5707760.html