HDU 2196 樹形DP經典題

2021-07-02 13:53:16 字數 1237 閱讀 1415

//經典的樹形dp題。

//題意是求樹中每個點到所有葉子節點的距離的最大值是多少。

//由於對於乙個節點來說,可能得到的距離最大的值的路徑來自他的子樹,

//或者從他的父節點過來,所以用兩次dfs。

//第一次dfs求出所有節點在他的子樹範圍內到葉子節點距離的最大值和第二大的值,第二次dfs更新從父節點過來的情況就可以了。

//因為如果只存最大值的話,判斷乙個點的從父節點過來的最大值,那麼如果他的父節點存的最大值正好是從該點過來的,那麼就失去

//了從父節點過來的狀態,所以要記錄最大的兩個值。

////乙個有n個結點的樹,給你相鄰兩個結點的距離,問你對於第i個結點,樹中離i最遠的結點的距離是多少。

//題解:可以通過兩次樹形dp求解。dp[i][3],i表示為在**結點,0表示子樹中的最長距離,1表示子樹中的次長距離,2表示父樹的最長距離。

//如果結點a本身就是父結點b最長子樹距離上的結點,那麼結點a最長父樹結點就是結點b的次長子樹距離或者結點b的最長父樹距離。

#include#includeusing namespace std;

#define max 10005

#define max(a,b) ((a)>(b)?(a):(b))

int dp[max][3];

int edge[max<<1];//表示第i條邊的終點

int next[max<<1];//與第i條邊同起點的下一條邊的位置

int head[max<<1];//以i為起點的第一條邊的儲存位置

int cost[max<<1];

void insert(int i,int a,int b,int c)//a起點,b終點

void dp1(int x,int pre)

else if(dp[pre][0]>dp[x][2]) dp[x][2]=dp[pre][0];

dp[x][2]+=len;

}for(int i=head[x]; i!=-1; i=next[i])

if(edge[i]!=pre) dp2(edge[i],x);

}int main()

dp1(1,-1);//求子樹最長路

dp2(1,-1);//求父樹最長路

for(int i=1; i<=n; ++i)

printf("%d\n",max(dp[i][0],dp[i][2]));

}return 0;

}

HDU 2196 經典樹形DP

大體思路是將乙個無根數轉化為有根樹,再深搜兩次,第一次將每個子樹的根距其葉子的最遠距離求出來 自下而上 第二次求每個節點到其他結點的最遠距離 自上而下 但因為在第二次深蒐時可能會碰到乙個結點的父節點的最遠距離經過它,所以我們需要儲存乙個最長距離和乙個次長距離 include include incl...

HDU 2196 樹形dp入門

鏈結 傳送門 題意 給你乙個n個節點的棵樹,然後給你和 第i臺電腦與第a臺電腦相連的花費 v 問你最長的線路是多長 求樹上任意節點所能達到的最遠點的距離 樹形dp 開個陣列 分別記錄這個點到子樹最遠節點的最長距離和次長距離和記錄到父節點上的最長距離這樣在樹上dp 1.求子樹最長和次長 dp u 0 ...

題解 hdu2196 樹形DP

題目鏈結 分析 求乙個樹中所有節點能到達的最遠距離f i 要用兩個dfs。首先第乙個dfs求出所有每個節點i在其子樹中的正向最大距離和正向次大距離和dist i 0 和dist i 1 如果i節點在子樹中最大距離經過了2號兒子,那麼次大距離就是不經過2號兒子的最大距離 並且還要標記longest i...