hdu 2196 Computer

题意: N 个点 N-1条边 每条边有权值 求每个点所能达的最长距离
// 树形dp 2次dfs 一次转成有根树、并求出每个子树(以i为根)到叶子节点的最大距离 还有就是从与i相连的个子节点j遍历下去的最大距离
// 其实 每个子树(以i为根)到叶子节点的最大距离 就是 max(child[i][j]);

#include <iostream> #include <algorithm> #include <queue> #include <math.h> #include <stdio.h> #include <string.h> #include <vector> using namespace std; #define MOD 1000000007 #define maxn 10010 vector<__int64> E[maxn],V[maxn],child[maxn];// E[i][id] 表示 i连出的节点 E[i][id] V[i][id]是对应的边权值 child[i][id]为以各个子节点遍历的各个最大值 __int64 ans[maxn],from[maxn],father[maxn];// ans[i]表示以i为根的树 i到叶子的最大值 ans[i]=max(child[i][id]) id=0,1,..len-1.
// from[i] 表示ans[i]是由哪个点得到的 father[i]表示 i到除去以i为根的树之外的点的最大值就是从父节点那里可以到达i来的最大值
int n; __int64 dfs1(int u){ int i,v,id; __int64 tp,rt=-1; int len=E[u].size(); if(!len) return 0; for(i=0;i<len;i++){ v=E[u][i]; tp=dfs1(v); tp+=V[u][i]; // printf("tp= %I64d\n",tp); child[u].push_back(tp); if(tp>rt){ rt=tp; id=v; } } from[u]=id; return ans[u]=rt; } void dfs2(int u){ int i,v; __int64 tp; int len=E[u].size(); if(!len) return; for(i=0;i<len;i++){ v=E[u][i]; tp=0;//忘记把 tp放进来初始化了、白白WA了次 if(from[u]!=v){ tp=ans[u]+V[u][i]; if(tp>ans[v]){ ans[v]=tp; from[v]=u; } father[v]=tp; } else{ for(int j=0;j<len;j++) if(j!=i) tp=max(tp,child[u][j]); // printf("u=%d %I64d\n",u,tp); father[v]=max(father[u],tp)+V[u][i]; tp=max(father[u]+V[u][i],tp+V[u][i]); if(tp>ans[v]){ ans[v]=tp; from[v]=u; } } dfs2(v); } } int main() { int i,k; int val; while(scanf("%d",&n)!=EOF){ for(i=1;i<=n;i++){ E[i].clear(); V[i].clear(); child[i].clear(); ans[i]=0; from[i]=i; } father[1]=0; for(i=2;i<=n;i++) { scanf("%d %d",&k,&val); E[k].push_back(i); V[k].push_back(val); } dfs1(1); //printf("ddd="); dfs2(1); // printf("%I64d ",child[2][1]); for(i=1;i<=n;i++) printf("%I64d\n",ans[i]); //printf("%I64d\n",ans[i]); } return 0; }

 

你可能感兴趣的:(com)