標籤:acm c語言 演算法 編程 樹形dp
兩次DFS,先從下往上搜一次,記錄每個點到子樹的最長距離與次長距離。次長距離的目的是如果在第二次更新的時候,最長距離與該子節點的方向是同一個方向,那就不能用這個最長距離了,只能用次長距離來更新。那麼第二次dfs就是來從上往下來更新狀態的。
代碼如下:
#include <iostream>#include <string.h>#include <math.h>#include <queue>#include <algorithm>#include <stdlib.h>#include <map>#include <set>#include <stdio.h>using namespace std;#define LL __int64#define pi acos(-1.0)const int mod=100000000;const int INF=0x3f3f3f3f;const double eqs=1e-8;int head[11000], cnt, dp[11000][3], id[11000][3];struct node { int u, v, w, next;} edge[30000];void add(int u, int v, int w){ edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++;}void dfs1(int u, int fa){ int i; for(i=head[u]; i+1; i=edge[i].next) { int v=edge[i].v; if(v==fa) continue ; dfs1(v,u); if(dp[u][1]<dp[v][0]+edge[i].w) { dp[u][1]=dp[v][0]+edge[i].w; id[u][1]=v; if(dp[u][1]>dp[u][0]) { swap(dp[u][0],dp[u][1]); swap(id[u][1],id[u][0]); } } }}void dfs2(int u, int fa){ int i, tmp; for(i=head[u]; i+1; i=edge[i].next) { int v=edge[i].v; if(v==fa) continue ; if(id[u][0]==v) tmp=dp[u][1]; else tmp=dp[u][0]; if(dp[v][1]<edge[i].w+tmp) { dp[v][1]=edge[i].w+tmp; id[v][1]=u; if(dp[v][1]>dp[v][0]) { swap(dp[v][1],dp[v][0]); swap(id[v][1],id[v][0]); } } dfs2(v,u); }}void init(){ memset(head,-1,sizeof(head)); cnt=0;}int main(){ int n, i, u, v, w; while(scanf("%d",&n)!=EOF) { init(); for(i=2; i<=n; i++) { scanf("%d%d",&v,&w); add(i,v,w); add(v,i,w); } memset(dp,0,sizeof(dp)); dfs1(1,0); dfs2(1,0); for(i=1; i<=n; i++) { printf("%d\n",dp[i][0]); } } return 0;}
HDU 2196 Computer (樹形DP)