1. 程式人生 > >Computer HDU - 2196(樹形dp)

Computer HDU - 2196(樹形dp)

main 遞歸 最大路 ont next bit namespace ems bits

題目要求:求樹上每個點能到達的最遠距離

dp[u][0]:u的子樹下u的最遠距離是多少

dp[u][1]:u的子樹次遠距離是多少

dp[u][2]:u的父親能走的最遠距離是多少

dp[0] [1]dfs處理即可

如果vi不是u最長距離經過的節點,f[vi][1] = dist(vi,u)+max(f[u][0], f[u][1])
如果vi是u最長距離經過的節點,那麽不能選擇f[u][0],因為這保存的就是最長距離,要選擇u次大距離

#include<bits/stdc++.h>

#define mem(a,b) memset(a,b,sizeof(a))
using
namespace std; const int maxn=1e5+10; struct edge{ int u,v,w,next; }e[maxn]; int g[maxn],tot=0; int dp[maxn][3]; void creat_edge(int u,int v,int w) { e[++tot]=(edge){u,v,w,g[u]}; g[u]=tot; } void dfs(int u)//遞歸求得u子樹中的最大與次大 0最大 1次大 { for(int i=g[u];i>0;i=e[i].next) {
int v=e[i].v; dfs(v); int w=e[i].w; int temp= dp[v][0]+w; if(temp>=dp[u][0]) { dp[u][1]=dp[u][0]; dp[u][0]=temp; } else if(temp>dp[u][1]) dp[u][1]=temp; } } void dfs1(int u) { for(int
i=g[u];i>0;i=e[i].next) { int v=e[i].v,w=e[i].w; if(dp[u][0]==dp[v][0]+w)//如果當前節點在最大路徑上 只能取次大路徑 dp[v][2]=max(dp[u][2],dp[u][1])+w; else dp[v][2]=max(dp[u][2],dp[u][0])+w; dfs1(v); } } int main() { int n; while(~scanf("%d",&n)) { mem(g,0); mem(dp,0); for(int i=2;i<=n;i++) { int u=i,v,w; scanf("%d%d",&v,&w); creat_edge(v,u,w); // creat_edge(v,u,w); } dfs(1); dfs1(1); for(int i=1;i<=n;i++) cout<<max(dp[i][0],dp[i][2])<<"\n"; } return 0; }

Computer HDU - 2196(樹形dp)