題解 hdu2196 樹形DP

2021-08-22 19:40:26 字數 1521 閱讀 9197

題目鏈結

分析:求乙個樹中所有節點能到達的最遠距離f[i]。要用兩個dfs。

首先第乙個dfs求出所有每個節點i在其子樹中的正向最大距離和正向次大距離和dist[i][0]和dist[i][1](如果i節點在子樹中最大距離經過了2號兒子,那麼次大距離就是不經過2號兒子的最大距離)。並且還要標記longest[i]=j表示節點i在其子樹中的最大距離經過了節點j(即j是i的乙個兒子)。

由上步我們獲得了正向最大距離,正向次大距離和最大距離的兒子節點標記。畫圖可以知道我們建立的這棵樹,i節點的最遠距離只有兩種選擇:i節點所在子樹的最大距離,或者i節點連線它的父節點所能到達的最大距離。(即前者往下走,後者先往上走之後很可能也往下走)

所以我們只要求出反向最大距離dist[i][2](即i節點往它的父節點走所能到達的最大距離)就可以知道i節點在整個樹中能走的最大距離了。

dist[i][2]求法:i節點往它的父節j點走,如果它的父節點的正向最大距離不經過i的話,那麼dist[i][2]要不就是它父節點的反向最大距離+w[i][j]要不就是它父節點的正向最大距離+ w[i][j].

如果它的父節點的正向最大距離經過i的話,那麼dist[i][2]要不就是它父節點的反向最大距離+w[i][j]要不就是它父節點的正向次大距離+ w[i][j].

上面就是dfs2要求的值。最終f[i] = max(dist[i][0],dist[i][2])

#include

#include

#include

using

namespace

std;

const

int n=1e4+200;

struct edgeedges[n*2];

int tot;//總邊數

int head[n];//head[u]=i以u為起點的第一條邊是i

void add_edge(int u,int v,int w)//新增從u->v,權值為w的邊

int dist[n][3];//dist[i][0,1,2]分別為正向最大距離,正向次大距離,反向最大距離

int longest[n];//記錄最大子樹經過的子節點

int dfs1(int u,int fa)//返回u的最大正向距離

else

if(dist[u][1]//u的正向次大距離小於子節點v的正向最大距離加邊權

dist[u][1]=max(dist[u][1],dfs1(v,u)+edges[e].w);//更新次大距離

}return dist[u][0];//返回最大距離

} void dfs2(int u,int fa)

}int main()

dfs1(1,-1);//更新正向最大距離和次大距離

dfs2(1,-1);//更新反向最大距離

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

printf("%d\n",max(dist[i][0],dist[i][2]));//兩者取最值即為所求

}return

0;}

HDU 2196 樹形dp入門

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

HDU 2196 經典樹形DP

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

HDU 2196 樹形DP經典題

經典的樹形dp題。題意是求樹中每個點到所有葉子節點的距離的最大值是多少。由於對於乙個節點來說,可能得到的距離最大的值的路徑來自他的子樹,或者從他的父節點過來,所以用兩次dfs。第一次dfs求出所有節點在他的子樹範圍內到葉子節點距離的最大值和第二大的值,第二次dfs更新從父節點過來的情況就可以了。因為...