• HDU 2196:Computer 树形DP


    Computer

    题目链接:

    http://acm.hdu.edu.cn/submit.php?pid=2196

    题意:

    学校里有一台电脑(编号为1),这些年来又陆续买了(N-1)台电脑,每一台新电脑都要和一台已经存在的电脑连接,构成了一棵以1为根的树,求树上每个节点到所有叶子节点的距离的最大值。

    题解:

     先跑一遍DFS记录下val1(“以V为根的子树”的最远叶子节点的距离)和val2(与路径[V到其最远叶子节点]没有公共路径的最远的叶子节点的距离)

    可以发现 当前节点V到其他所有点的最大值可能由三种情况得到:

      ①其父亲节点Fa到以“Fa为根的子树”的最远叶子节点的距离val1(注意这里,当这个最远节点同时也是V的最远节点时不可取,应取Fa对应的val2)+Fa到V的边权

        ②当前节点到其下的叶子节点的最大距离val1

      ③其父亲节点Fa到除了“以Fa为根的子树”上的节点外  最远的节点的距离(设其为fa)+Fa到V的边权

    可以知道①和②的答案都已经在第一次的DFS中求出来了,要求的就是③的值

    再进行一遍DFS,即可得到答案

                 

    代码

    #include<stdio.h>
    #include<vector>
    using namespace std;
    const int N=10001;
    struct edge
    {
      int to,val;
      edge(int x=0,int y=0)
      {
        to=x,val=y;
      }
    };
    int mmax(int a,int b,int c)
    {
      return a>b?(a>c?a:c):(b>c?b:c);
    }
    vector<edge>q[N];
    struct node
    {
      int value,fa,val1,val2,son1,son2;
    }t[N];
    void Dfs_Findval(int id)
    {
      int m=1,son1,son2;
      for(int i=0;i<q[id].size();++i)
      {
        int to=q[id][i].to;
        Dfs_Findval(to);
        int val=q[id][i].val+t[to].val1;
        int son=t[to].son1;
        if(val>t[id].val1)
        {
          t[id].val2=t[id].val1;
          t[id].son2=t[id].son1;
          t[id].val1=val;
          t[id].son1=son;
        }
        else if(val>t[id].val2)
         {
          t[id].val2=val;
          t[id].son2=son;
        }
        m=0;
      }
      if(m)t[id].son1=t[id].son2=id;
      return ;
    }
    void Dfs_Findans(int id)
    {
      for(int i=0;i<q[id].size();++i)
      {
        int to=q[id][i].to;
        int V=q[id][i].val;
        if(t[to].son1!=t[id].son1)
        {
          t[to].fa=mmax(t[id].val1+V,t[id].fa+V,0);
          t[to].value=mmax(t[to].val1,t[id].fa+V,t[id].val1+V);
        }
        else
        {
          t[to].fa=mmax(t[id].val2+V,t[id].fa+V,0);
          t[to].value=mmax(t[to].val1,t[id].fa+V,t[id].val2+V);
        }
        Dfs_Findans(to);
      }
    }
    void solve()
    {
      int n,x,y;
      while(~scanf("%d",&n))
      {
        for(int i=1;i<=n;++i)
        {
          q[i].clear();
          t[i].val1=t[i].val2=t[i].fa=0;
        }
        for(int i=2;i<=n;++i)
        {
          scanf("%d%d",&x,&y);
          q[x].push_back(edge(i,y));
        }
        Dfs_Findval(1);
        Dfs_Findans(1);
        printf("%d ",t[1].val1);
        for(int i=2;i<=n;++i)
        printf("%d ",t[i].value);
      }
    }
    int main()
    {
      solve();
    }

      

  • 相关阅读:
    REVERSE-Daily(4)-Elfcrackme2
    DES带IV向量加密解密工具
    Reverse-Daily(3)-DotNetCrackMe1
    Reverse-Daily(2)-wow
    C#:using和new关键字
    python3实现UDP协议的简单服务器和客户端
    python3实现TCP协议的简单服务器和客户端
    深入C++的运算符重载
    NLTK学习笔记(五):分类和标注词汇
    NLTK学习笔记(四):自然语言处理的一些算法研究
  • 原文地址:https://www.cnblogs.com/kiuhghcsc/p/5592190.html
Copyright © 2020-2023  润新知