HDU 2196 Computer (樹上最遠距離)
阿新 • • 發佈:2018-12-21
題意:給你一棵樹,之後讓你求出這個樹上每個點的距離的最大值。
思路:首先怎樣求一個樹上一個點到另外一個點的最遠距離?其實就是一個點往父親方向的最大值+往兒子方向的最大值,可知這些東西肯定都是單向的,因為你要麼往兒子方向走你就只能往兒子方向走,不能再回去往父親方向走,那麼我們就可以設:
f[u]表示的是你往兒子方向的最大值,
g[u]表示的是你往父親方向的最大值,
p[u]表示的是u的父親,那麼就有:
f[u] = max(f[v] + w(u,v)) // v 是 u 的兒子
g[u] = w(p[u],u) + max(g[p[u]] , w(u,v) + f[u]) // v 是 u的兄弟。
解釋一下g[u]這個dp方程首先就是我們遍歷u的父親節點,最大值是怎樣轉移的?有兩種情況1:從u的父親哪裡轉移,2從u的兄弟哪裡拐過來的,之後求一個最大值就好了
程式碼:
#include <bits/stdc++.h> using namespace std; const int maxn = 10000 + 10; vector<pair<int,int> >G[maxn]; int p[maxn] , f[maxn] , g[maxn]; void dfs1(int u,int fa) { p[u] = fa; for(int i = 0 ; i < G[u].size() ; i ++) { int v = G[u][i].first , w = G[u][i].second; if(v == fa) continue; dfs1(v,u); f[u] = max(f[v] + w , f[u]); } } void dfs2(int u , int fa) { int t = 0; g[u] = g[fa]; for(auto i : G[fa]) { int v = i.first , w = i.second; if(v == p[fa]) continue; if(v == u) t = w; else g[u] = max(g[u] , f[v] + w); } g[u] += t; for(auto i : G[u]) { int v = i.first; if(v == fa) continue; dfs2(v,u); } } int main() { int n; while(scanf("%d",&n)!=EOF) { memset(f,0,sizeof(f)); memset(g,0,sizeof(g)); for(int i = 1 ; i <= n ;i ++) G[i].clear(); int v , w; for(int u = 2 ; u <= n ; u++) { scanf("%d%d",&v,&w); G[u].push_back(make_pair(v,w)); G[v].push_back(make_pair(u,w)); } dfs1(1,0); dfs2(1,0); for(int i = 1 ; i <= n ; i++) printf("%d\n",max(f[i],g[i]));