樹形dp學習

2022-05-06 15:39:11 字數 1741 閱讀 5835

學習部落格:

樹的性質:n個點,n-1條邊,任意兩個點之間只存在一條路徑,可以人為設定根節點,對於任意乙個節點只存在至多乙個父節點,其餘為子節點。

記憶化樹形dp模型較為抽象難以理解,以下通過由淺到深的方式解析樹形dp以及樹的性質。

樹形dp求樹的直徑:(在一顆樹里找到點x,y,使得|xy|最大)

如圖,我們令a為根節點,令dfs遍歷順序為abdghefc。

在我們的dfs計算過程中,我們從下往上求解每乙個節點,總的來說我們要求兩個東西:

1、以每乙個節點為根,所能到達的最長路徑dp【u】

2、以每乙個節點為根,它下面的的樹的最長路徑ans(其實就是找到 兩個沒有重複路徑的子樹,例如以b為根節點,會找到bdg+be而不會找到bdg+bdh)

然後將子樹中以子樹根為起點所能到達的最長路徑傳給父節點,最後得出答案

具體看下面**:

struct

node

;vector

node[maxn];//

node[u][i].nex代表該節點的子節點 node[u][i].val代表該節點與子節點之間路徑的權值

void dfs(int u,int fa)//

該節點和該節點的父親}}

理解了基本的樹形dp之後,開始下面的練習:

題目大意:在一顆有n(n<5e4)個節點的樹中,每個節點有權值和是否有陷阱,你可以最多踏進c(c<=3)個陷阱,當你進入第c個陷阱時,你就無法繼續移動了,你可以在任意節點出發,獲取經過節點的權值(無法重複獲取同乙個節點),求能得到的最大權值和。

思路:有點像樹鏈剖分,對於乙個以u為根的子樹,因為每個頂點只能經過一次,那我們只能選擇它的乙個子樹往下走。就像是把這棵樹分成許多鏈,最後再連線起來。

這道題目麻煩的地方是陷阱的處理,用d【u】【j】【0/1】表示以u為根的某一子節點經過j個陷阱後到達u的最大權值和,0/1表示起點是否有陷阱。

假設當前到達u時經過了k個陷阱,分下面幾種情況進行討論:

①如果k==c,那麼起點和終點至少有乙個是陷阱(可能有些人會認為終點一定會是陷阱,這樣是沒錯的,因為起點和終點時相對的,你也可以把起點看做終點)。

②如果k具體看**:

#include#include

#include

#include

using

namespace

std;

const

int maxn=50000+5

;int

n,c;

intans;

vector

g[maxn];

int val[maxn],trap[maxn];//

分別儲存節點的值和是否有陷阱

int d[maxn][5][2];//

d[u][j][0/1]表示以u為根的某一子節點經過j個陷阱之後到達u的最大權值和

void dfs(int u,int

fa) }

for(int j=0;j+trap[u]<=c;j++)}}

}}int

main()

ans=0

; memset(d,

0,sizeof

(d));

dfs(

0,-1

); cout}}

樹形dp學習

練習專題參考 傳送門 hdu 1520 題意 給出n個點,然後給出n個點對應的歡樂值,然後給出n 1條邊,a b,表示b是a的直屬上級,現在舉行乙個patry,但是要求員工和他的直屬上級不能同時來,問來的人的歡樂值的最大和是多少 思路 首先明確這是一棵有向樹,dp i 0 1 代表第i個人來 不來的...

樹形dp初次學習

1 什麼是樹型動態規劃 顧名思義,樹型動態規劃就是在 樹 的資料結構上的動態規劃,平時作的動態規劃都是線性的或者是建立在圖上的,線性的動態規劃有二種方向既向前和向後,相應的線性的動態規劃有二種方法既順推與逆推,而樹型動態規劃是建立在樹上的,所以也相應的有二個方向 1 葉 根 在回溯的時候從葉子節點往...

樹形DP學習總結

概述 樹形dp是dp的一種,有時候會和區間dp結合。由於樹有著天然的遞迴結構 父子結構 而且它作為一種特殊的圖 可以描述許多複雜的資訊 因此在樹就成了一種很適合dp的框架 問題 給你一棵樹 要求用最少的代價 最大的收益 完成給定的操作 樹形dp 一般來說都是從葉子從而推出根 當然 從根推葉子的情況也...