首页 > 代码库 > HDU-2196 Computer (树形DP)
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)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。