HDU-2196 Computer (树形DP)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU-2196 Computer (树形DP)相关的知识,希望对你有一定的参考价值。
最近在看树形DP,这题应该是树形DP的经典题了,写完以后还是有点感觉的。之后看了discuss可以用树分治来做,以后再试一试。
题目大意
找到带权树上离每个点的最远点。︿( ̄︶ ̄)︿
题解:
对于每一个点的最远点,就是以这个点为根到所有叶子节点的最长距离。但是如果确定根的话,除了根节点外,只能找到每个节点(度数-1)个子树的最大值,剩下一个子树是该节点当前的父亲节点。
所以当前节点的最远点在当前节点子树的所有叶子节点以及父亲节点的最远点上(当父亲节点的最远点不在当前节点的子树上时),
如果父亲节点的最远点在当前子树上时候,取父亲节点的第二大最远点子树上。(具体的看代码)
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define MAX_NUM 10020 #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long int LL; struct no { LL v,next,w; }edge[4*MAX_NUM]; int stu[MAX_NUM]; int col = 0; void add(LL u , LL v,LL w){ edge[col].v = v; edge[col].w = w; edge[col].next = stu[u]; stu[u] = col++; } LL dp[MAX_NUM][2]; LL sec[MAX_NUM]; LL sett[MAX_NUM]; bool flag[MAX_NUM]; LL fdfs(LL u){ dp[u][0] = 0; for (int i = stu[u]; i != -1 ; i = edge[i].next){ LL v = edge[i].v; if(!flag[v]){ flag[v] = true; LL num = fdfs(v)+edge[i].w; if(num>=dp[u][0]){ sec[u] = dp[u][0]; dp[u][0] = num; sett[u] = v; } else if(num>=sec[u]){ sec[u] = num; } } } return dp[u][0]; } void ddfs(LL u){ for (int i = stu[u]; i != -1 ; i = edge[i].next){ LL v = edge[i].v; if(!flag[v]){ flag[v] = true; if(sett[u]!=v) dp[v][1] = max(dp[u][0], dp[u][1])+edge[i].w; else dp[v][1] = max(sec[u],dp[u][1])+edge[i].w; ddfs(v); } } } int main(int argc, char const *argv[]) { int n; while(~scanf("%d",&n)){ mem(dp,0); mem(flag,false); mem(sett,0); mem(stu,-1); mem(sec,-1); LL a,b; col = 0; for (int i = 2; i <= n ; ++i) { scanf("%lld%lld",&a,&b); add(i,a,b); add(a,i,b); } flag[1] = true; fdfs(1); mem(flag,false); flag[1] = true; ddfs(1); for (int i = 1; i <= n ; ++i) { printf("%lld\n",max(dp[i][0],dp[i][1])); } } return 0; }
以上是关于HDU-2196 Computer (树形DP)的主要内容,如果未能解决你的问题,请参考以下文章