標籤:
給出一棵樹,邊有權值,求出離每一個節點最遠的點的距離
樹形DP,經典題
本來這道題是無根樹,可以隨意選擇root,
但是根據輸入資料的方式,選擇root=1明顯可以方便很多。
我們先把邊權轉化為點權,放在數組cost中
令tree(i)表示以節點i為根的子樹
對於節點i,離該節點最遠的點要不就是在tree(i)中,要不就是在father(i)上面
令:
dp[i][1] : 在子樹tree(i)中,離i最遠的距離
dp[i][2] : 在子樹tree(i)中,離i第二遠的距離 (遞推的時候需要)
dp[i][0] : 在樹tree(root)-tree(i)中,離i最遠的距離
son[i] : 在子樹tree(i)中,離i最遠的點是在tree(son[i])中,即最遠路徑經過節點son[i]
則對於每一個i,離i最遠的距離=max(dp[i][0],dp[i][1])
流程:
0.鏈式前向星建樹
1.dfs1,確定dp[i][1]
2.dfs2,確定dp[i][2]
dfs1和dfs2都很簡單
3.dfs3,遞推確定dp[i][0]
1 #include<cstdio> 2 #include<cstring> 3 4 using namespace std; 5 6 const int maxn=10000+5; 7 const int inf=0x3f3f3f3f; 8 9 inline int max(int a,int b) 10 { 11 return a>b?a:b; 12 } 13 14 struct Edge 15 { 16 int to,next; 17 }; 18 Edge edge[maxn]; 19 int head[maxn]; 20 int tot; 21 int cost[maxn]; 22 int son[maxn]; 23 int dp[maxn][3]; 24 25 void init() 26 { 27 memset(head,-1,sizeof head); 28 tot=0; 29 memset(dp,0,sizeof dp); 30 memset(son,-1,sizeof son); 31 } 32 33 void addedge(int u,int v) 34 { 35 edge[tot].to=v; 36 edge[tot].next=head[u]; 37 head[u]=tot++; 38 } 39 40 void solve(int n); 41 void dfs1(int u,int pre); 42 void dfs2(int u,int pre); 43 void dfs3(int u,int pre); 44 45 int main() 46 { 47 int n; 48 while(~scanf("%d",&n)) 49 { 50 init(); 51 cost[1]=0; 52 for(int i=2;i<=n;i++) 53 { 54 int u; 55 scanf("%d %d",&u,&cost[i]); 56 addedge(u,i); 57 } 58 solve(n); 59 } 60 return 0; 61 } 62 63 void solve(int n) 64 { 65 dfs1(1,-1); 66 dfs2(1,-1); 67 dp[1][0]=0; 68 dfs3(1,-1); 69 70 for(int i=1;i<=n;i++) 71 { 72 printf("%d\n",max(dp[i][0],dp[i][1])); 73 } 74 return ; 75 } 76 77 void dfs1(int u,int pre) 78 { 79 for(int i=head[u];~i;i=edge[i].next) 80 { 81 int v=edge[i].to; 82 dfs1(v,u); 83 if(dp[v][1]+cost[v]>dp[u][1]) 84 { 85 dp[u][1]=dp[v][1]+cost[v]; 86 son[u]=v; 87 } 88 } 89 } 90 91 void dfs2(int u,int pre) 92 { 93 for(int i=head[u];~i;i=edge[i].next) 94 { 95 int v=edge[i].to; 96 dfs2(v,u); 97 if(v==son[u]) 98 continue; 99 if(dp[v][1]+cost[v]>dp[u][2])100 dp[u][2]=dp[v][1]+cost[v];101 }102 }103 104 void dfs3(int u,int pre)105 {106 for(int i=head[u];~i;i=edge[i].next)107 {108 int v=edge[i].to;109 if(v==son[u])110 {111 dp[v][0]=max(dp[u][0],dp[u][2])+cost[v];112 }113 else114 {115 dp[v][0]=max(dp[u][0],dp[u][1])+cost[v];116 }117 dfs3(v,u);118 }119 }
View Code
HDU 2196 Computer 樹形DP 經典題