zoukankan      html  css  js  c++  java
  • 中南大学oj 1317 Find the max Link 边权可以为负的树上最长路 树形dp 不能两遍dfs

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1317
    经典问题:
    树上最长路,边权可以为负值的,树形dp,不能用两边dfs。
    反例:
    5 4
    1 2 2
    2 3 1
    2 4 -100
    4 5 10
    写树形dp的时候,WA了好多次,错误在于:
    记录单链的时候,一个节点的最长单链不一定等于:边权+孩子的最长单链
    还可以不选孩子,只要边权就行!!!!!!
    如果边权非负的话,就是 边权+孩子的最长单链 了。

    思路:

      dp[u][0],记录的是以u为根结点的子树中的最长路

      dp[u][1],记录的是以u为起点的向下的一条最长链

    转移时:

      a记录的是max{ dp[sons][0] } 

      b和c记录的分别是dp[sons][1]的最大值和次大值

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<vector>
     4 using namespace std;
     5 const int N = 50005;
     6 typedef long long LL;
     7 LL inf = N * 100000ll;
     8 
     9 inline LL max(LL a,LL b)    {return a>b?a:b;}
    10 inline LL max(LL a,LL b,LL c)    {return (a>b?a:b)>c?(a>b?a:b):c;}
    11 
    12 LL dp[N][2];
    13 vector<int> G[N];
    14 struct edge
    15 {
    16     int to,w;
    17 }edges[2*N];
    18 
    19 void dfs(int u,int fa)
    20 {
    21     int sz=G[u].size(),v,w;
    22     LL temp;
    23     LL a=-inf,b=-inf,c=-inf;
    24     for(int i=0;i<sz;i++)
    25     {
    26         v = edges[G[u][i]].to;
    27         w = edges[G[u][i]].w;
    28         if( v!=fa )
    29         {            
    30             dfs(v,u);
    31             temp = max(dp[v][1]+w,w);
    32             a = max(a,dp[v][0]);
    33             if( temp > b )
    34             {
    35                 c = b;
    36                 b = temp;
    37             }
    38             else if( temp > c )
    39                 c = temp;            
    40         }
    41     }
    42     dp[u][0]=max(a,b,b+c);
    43     dp[u][1]=b;
    44 }
    45 
    46 int main()
    47 {
    48     int n,m;
    49     int u,v,w;
    50     
    51     while( ~scanf("%d%d",&n,&m) )
    52     {
    53         for(int i=1;i<=n;i++)    G[i].clear();
    54         for(int i=1;i<=m;i++)
    55         {
    56             scanf("%d%d%d",&u,&v,&w);
    57             edges[i].to = v;
    58             edges[i+m].to = u;
    59             edges[i].w = edges[i+m].w = w;
    60             G[u].push_back(i);
    61             G[v].push_back(i+m);
    62         }
    63         dfs(1,0);
    64         LL ans = -inf;
    65         for(int i=1;i<=n;i++)
    66             ans = max(ans,dp[i][0]);
    67         printf("%lld
    ",ans);
    68         //cout<<ans<<endl;
    69     }
    70     return 0;
    71 }
    View Code
  • 相关阅读:
    星力九代 命中算法源代码 特殊用户处理 点控调整
    Navicat for PostgreSQL 必须知道的十大功能
    如何在某个按钮上触发 bootstarp Modal 组件
    yii2.0 DetailView 自定义样式
    Jquery 利用单个复选款(checkbox)实现全选、反选
    【转载】CentOS LVM磁盘扩容
    VMware ESXi CentOS Linux虚拟机安装VMware Tools教
    Shell 脚本编程
    powershell学习
    Ruby应用记录:修改文件中某个字符串
  • 原文地址:https://www.cnblogs.com/kiwi-bird/p/3294487.html
Copyright © 2011-2022 走看看