hdu2196Computer 树形DP

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

思路:

一看就是一道树形DP的题目,对于一个节点来说,到它的最远距离的路径可能来于子树,也可能来源于经过父亲节点的路径,所以我们两次DFS即可。

第一次DFS自底向上(从叶节点开始),依次求出每个节点的在其子树上的最大距离和次大距离

第二次DFS自顶向下(从根节点开始),通过比较经过父亲节点的路径的最大距离和来源于子树的最大距离比较然后更新最大距离

至于为什么要保存次大距离呢??因为经过父亲节点的最大距离可能刚好经过当前的孩子节点,那么我们就只能通过当前孩子到父亲节点的距离加上经过父亲节点的路径次大值和当前节点的位于其子树的路径的最大距离的比较来更新最大距离咯。

虽然思路还是比较清晰的,自己实现起来还是比较难的。。。。

代码如下:

  1 #include<cstdlib>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<iostream>
  5 using namespace std;
  6 #define MAX 10010
  7 class node
  8 {
  9    public:
 10    int to;
 11    int w;
 12    int next;
 13   
 14 };
 15 node edge[2*MAX];
 16 int head[MAX];
 17 int tol;
 18 int maxn[MAX];
 19 int smaxn[MAX];
 20 int m_id[MAX];
 21 int sm_id[MAX];
 22 int vis[MAX];
 23 void init()
 24 {
 25     memset(head,-1,sizeof(head));
 26     memset(maxn,0,sizeof(maxn));
 27     memset(smaxn,0,sizeof(smaxn));
 28     memset(vis,0,sizeof(vis));
 29     tol=0;
 30 }
 31 void Build_Tree(int  u,int v,int w)
 32 {
 33     edge[tol].to=v;
 34     edge[tol].w=w;
 35     edge[tol].next=head[u];
 36     head[u]=tol++;
 37 }
 38 void dfs1(int root,int parent)
 39 {
 40         vis[root]=1;
 41         for(int i=head[root];i!=-1;i=edge[i].next)
 42         {
 43           if(vis[edge[i].to]) continue;
 44           int son=edge[i].to;
 45           dfs1(son,root);
 46           int len=edge[i].w;
 47           if(smaxn[root]<maxn[son]+len)
 48           {
 49               smaxn[root]=maxn[son]+len;
 50               sm_id[root]=son;
 51               if(smaxn[root]>maxn[root])
 52               {
 53                     swap(smaxn[root],maxn[root]);
 54                     swap(sm_id[root],m_id[root]);
 55               }
 56           }
 57         }
 58 }
 59 void dfs2(int root ,int  parent)
 60 {
 61     for(int i=head[root];i!=-1;i=edge[i].next)
 62     {
 63          if(edge[i].to==parent) continue;
 64          int son=edge[i].to;
 65          if(m_id[root]==son)
 66          {
 67               if(edge[i].w+smaxn[root]>smaxn[son])
 68               {
 69                     smaxn[son]=edge[i].w+smaxn[root];
 70                     sm_id[son]=root;
 71                     if(smaxn[son]>maxn[son])
 72                     {
 73                          swap(smaxn[son],maxn[son]);
 74                          swap(sm_id[son],m_id[son]);
 75                     }
 76               }
 77          }
 78          else
 79         {
 80             if(edge[i].w+maxn[root]>smaxn[son])
 81             {
 82                 smaxn[son]=edge[i].w+maxn[root];
 83                 sm_id[son]=root;
 84                 if(smaxn[son]>maxn[son])
 85                 {
 86                     swap(smaxn[son],maxn[son]);
 87                     swap(m_id[son],sm_id[son]);
 88                 }
 89             }
 90         }
 91         dfs2(son,root);
 92     }
 93 
 94 }
 95 int n;
 96 int main()
 97 {
 98         while(scanf("%d",&n)!=EOF)
 99         {
100             init();
101            for(int i=2;i<=n;i++)
102            {
103               int u,w;
104               scanf("%d%d",&u,&w);
105               Build_Tree(i,u,w);
106               Build_Tree(u,i,w);
107            }
108            dfs1(1,-1);
109            dfs2(1,-1);
110            for(int i=1;i<=n;i++)
111              cout<<maxn[i]<<endl;
112            
113         }
114         return 0;
115  }
View Code

 

posted on 2013-08-19 16:46  GyyZyp  阅读(214)  评论(0编辑  收藏  举报

导航