學習部落格:
樹的性質:n個點,n-1條邊,任意兩個點之間只存在一條路徑,可以人為設定根節點,對於任意乙個節點只存在至多乙個父節點,其餘為子節點。
記憶化樹形dp模型較為抽象難以理解,以下通過由淺到深的方式解析樹形dp以及樹的性質。
樹形dp求樹的直徑:(在一顆樹里找到點x,y,使得|xy|最大)
如圖,我們令a為根節點,令dfs遍歷順序為abdghefc。
在我們的dfs計算過程中,我們從下往上求解每乙個節點,總的來說我們要求兩個東西:
1、以每乙個節點為根,所能到達的最長路徑dp【u】
2、以每乙個節點為根,它下面的的樹的最長路徑ans(其實就是找到 兩個沒有重複路徑的子樹,例如以b為根節點,會找到bdg+be而不會找到bdg+bdh)
然後將子樹中以子樹根為起點所能到達的最長路徑傳給父節點,最後得出答案
具體看下面**:
struct理解了基本的樹形dp之後,開始下面的練習:node
;vector
node[maxn];//
node[u][i].nex代表該節點的子節點 node[u][i].val代表該節點與子節點之間路徑的權值
void dfs(int u,int fa)//
該節點和該節點的父親}}
題目大意:在一顆有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 一般來說都是從葉子從而推出根 當然 從根推葉子的情況也...