• hdu 2196 Computer(树形dp)


     题意:求树每个点到其他点的最远距离。
     思路:选择一点作为树的根,令dp[u][0]为点u从子树中取得的最长距离,dp[u][1]为点u从子树中取得的次长距离,dp[u][2]为从父亲节点取得的最长距离
     则最远距离为dp[u][0]或dp[u][2]
     dp[u][0]和dp[u][1]比较简单,一次深搜求得
     dp[u][2]有两种情况,设a为u的父亲节点
     当u在a子树取得最长距离的路径上时,dp[u][2] = max(dp[a][1], dp[a][2]) + dist(a,u);
     当u不在a子树取得最长距离的路径上时,dp[u][2] = max(dp[a][0], dp[a][2]) + dist(a,u);
     1 #include <cstdio>
     2 #include <cstring>
     3 #define N 10005
     4 
     5 int dp[N][3];
     6 int head[N], mark[N], eNum;
     7 struct Edge
     8 {
     9     int e, next, w;
    10 }edge[N*2];
    11 
    12 int max2(int x, int y)
    13 {
    14     return x > y ? x : y;
    15 }
    16 
    17 void init(int n)
    18 {
    19     memset(head, -1sizeof(head));
    20     memset(mark, 0sizeof(mark));
    21     eNum = 0;
    22 }
    23 
    24 void AddEdge(int u, int v, int w)
    25 {
    26     edge[eNum].e = v;
    27     edge[eNum].w = w;
    28     edge[eNum].next = head[u];
    29     head[u] = eNum++;
    30 }
    31 
    32 void input(int n)
    33 {
    34     int v, w;
    35     for(int u=2; u<=n; u++)
    36     {
    37         scanf("%d%d",&v, &w);
    38         AddEdge(u, v, w);
    39         AddEdge(v, u, w);
    40     }
    41 }
    42 
    43 void dfs(int u, int pre)
    44 {
    45     dp[u][0] = 0; dp[u][1] = 0;
    46     for(int i=head[u]; i!=-1; i=edge[i].next)
    47     {
    48         int v = edge[i].e, w = edge[i].w;
    49         if(v == pre) continue;
    50         dfs(v, u);
    51         if(dp[u][0]<dp[v][0]+w)
    52         {
    53             dp[u][1] = dp[u][0]; //先将最长距离赋给次长距离,再更新最长距离(低级错误)
    54             dp[u][0] = dp[v][0] + w;
    55             mark[u] = v;
    56         }
    57         else if(dp[u][1]<dp[v][0]+w)
    58             dp[u][1] = dp[v][0] + w;
    59     }
    60 }
    61 
    62 void solve(int u, int pre)
    63 {
    64     for(int i=head[u]; i!=-1; i=edge[i].next)
    65     {
    66         int v = edge[i].e, w = edge[i].w;
    67         if(pre == v) continue;
    68 
    69         if(mark[u]==v)
    70             dp[v][2] = max2(dp[u][1], dp[u][2]) + w;
    71         else
    72             dp[v][2] = max2(dp[u][0], dp[u][2]) + w;
    73         solve(v, u);
    74     }
    75 }
    76 
    77 int main()
    78 {
    79     int n;
    80     while(scanf("%d",&n)!=EOF)
    81     {
    82         init(n);
    83         input(n);
    84         dfs(10);
    85         dp[1][2] = 0;
    86         solve(10);
    87 
    88         for(int i=1; i<=n; i++)
    89             printf("%d ",max2(dp[i][0],dp[i][2]));
    90     }
    91     return 0;
    92 }
    View Code

  • 相关阅读:
    Luogu P4071 [SDOI2016]排列计数
    CF 961E Tufurama
    Luogu P2057 [SHOI2007]善意的投票
    Luogu P2756 飞行员配对方案问题
    POJ2151
    POJ 3349&&3274&&2151&&1840&&2002&&2503
    POJ 2388&&2299
    EZ 2018 03 30 NOIP2018 模拟赛(六)
    POJ 1459&&3436
    BZOJ 1001: [BeiJing2006]狼抓兔子
  • 原文地址:https://www.cnblogs.com/byluoluo/p/3614547.html
Copyright © 2020-2023  润新知