zoukankan      html  css  js  c++  java
  • HDU 3534 Tree (树形DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3534

    题意:给出一颗树(n个顶点,n-1条边)

    求最长的路径,以及最长路径的条数。

    路径无非就是连接两个点直接的路。

    因为是一颗树,所以连接两个点肯定是唯一的路径。

    其实就是求两点间距离的最大值,以及这个最大值有多少个。

    很裸的树形DP;

    首先统计出结点到叶子结点的最长距离和次长距离。

    然后找寻经过这个点的,在这个为根结点的子树中的最长路径个数目。

    代码:

    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <stdio.h>
    using namespace std;
    const int MAXN=100010;
    const int INF=0x3f3f3f3f;
    struct Node
    {
        int to,next,len;
    }edge[MAXN*2];
    int head[MAXN];
    int tol;
    int maxn[MAXN];//该节点往下到叶子结点的最大距离
    int smaxn[MAXN];// 次大距离
    int maxn_num[MAXN];//最大距离的个数
    int smaxn_num[MAXN];//次大距离的个数
    int path[MAXN];//该结点为根的子树中,包含该结点的最长路径长度
    int num[MAXN];//最长路径的长度
    
    void init()
    {
        tol=0;
        memset(head,-1,sizeof(head));
    }
    void add(int u,int v,int w)
    {
        edge[tol].to=v;
        edge[tol].len=w;
        edge[tol].next=head[u];
        head[u]=tol++;
        edge[tol].to=u;
        edge[tol].len=w;
        edge[tol].next=head[v];
        head[v]=tol++;
    }
    
    void dfs(int u,int pre)
    {
        maxn[u]=smaxn[u]=0;
        maxn_num[u]=smaxn_num[u]=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(v==pre)continue;
            dfs(v,u);
            if(maxn[v]+edge[i].len>maxn[u])
            {
                smaxn[u]=maxn[u];
                smaxn_num[u]=maxn_num[u];
                maxn[u]=maxn[v]+edge[i].len;
                maxn_num[u]=maxn_num[v];
            }
            else if(maxn[v]+edge[i].len==maxn[u])
            {
                maxn_num[u]+=maxn_num[v];
            }
            else if(maxn[v]+edge[i].len>smaxn[u])
            {
                smaxn[u]=maxn[v]+edge[i].len;
                smaxn_num[u]=maxn_num[v];
            }
            else if(maxn[v]+edge[i].len==smaxn[u])
            {
                smaxn_num[u]+=maxn_num[v];
            }
        }
        if(maxn_num[u]==0)//叶子结点
        {
            maxn[u]=smaxn[u]=0;
            maxn_num[u]=smaxn_num[u]=1;
            path[u]=0;
            num[u]=1;
            return;
        }
        int c1=0,c2=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(v==pre)continue;
            if(maxn[u]==maxn[v]+edge[i].len)c1++;
            else if(smaxn[u]==maxn[v]+edge[i].len)c2++;
        }
        path[u]=0;
        num[u]=0;
        if(c1>=2)//最长+最长
        {
            int tmp=0;
            path[u]=maxn[u]*2;
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].to;
                if(v==pre)continue;
                if(maxn[u]==maxn[v]+edge[i].len)
                {
                    num[u]+=tmp*maxn_num[v];
                    tmp+=maxn_num[v];
                }
            }
        }
        else if(c1>=1 && c2>=1)//最长+次长
        {
            path[u]=maxn[u]+smaxn[u];
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].to;
                if(v==pre)continue;
                if(maxn[u]==maxn[v]+edge[i].len)
                {
                    num[u]+=maxn_num[v]*smaxn_num[u];
                }
            }
        }
        else//最长
        {
            path[u]=maxn[u];
            num[u]=maxn_num[u];
        }
    }
    int main()
    {
        int n;
        while(scanf("%d",&n)==1)
        {
            int u,v,w;
            init();
            for(int i=1;i<n;i++)
            {
                scanf("%d%d%d",&u,&v,&w);
                add(u,v,w);
            }
            dfs(1,-1);
            int ans1=0,ans2=0;
            for(int i=1;i<=n;i++)
            {
                if(path[i]>ans1)
                {
                    ans1=path[i];
                    ans2=num[i];
                }
                else if(path[i]==ans1)
                    ans2+=num[i];
            }
            printf("%d %d\n",ans1,ans2);
        }
        return 0;
    }
    人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想
  • 相关阅读:
    各类免费资料及书籍索引大全(珍藏版)
    转—如何写一篇好的技术博客
    如何写技术博客
    Spring + Spring MVC + Mybatis 框架整合
    Httpclient 4.5.2 请求http、https和proxy
    HttpClient4.5.2 连接池原理及注意事项
    php加密数字字符串,使用凯撒密码原理
    php 阿里云视频点播事件回调post获取不到参数
    Nginx代理后服务端使用remote_addr获取真实IP
    记录:mac的浏览器访问任何域名、网址都跳转到本地127.0.0.1或固定网址
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3105215.html
Copyright © 2011-2022 走看看