給定一棵有n個節點的樹(通常是無根樹,也就是有n-1條無向邊),我們可以任選乙個節點為根節點,從而定義出每個節點的深度和每棵子樹的根。
在樹上設計動態規劃演算法時,一般就以節點從深到淺(子樹從小到大)的順序作為dp的「階段」。dp的狀態表示中,第一維通常是節點編號(代表以該節點為根的子樹)。大多數時候,我們採用遞迴的方式實現樹形動態規劃。對於每個節點x,先遞迴在它的每個子節點上進行dp,在回溯時,從子節點向節點x進行狀態轉移。
最大獨立子集的定義是,對於乙個樹形結構,所有的孩子和他們的父親存在排斥,也就是如果選取了某個節點,那麼會導致不能選取這個節點的所有孩子節點。一般詢問是要求給出當前這顆樹的最大獨立子集的大小(被選擇的節點個數)。
~~簡單的操作不說了~~
遞迴+回溯,分成選與不選,分別儲存,最後比個max
#include#includeusing namespace std;
vectorv[6005];
int h[6005], flag[6005], dp[6005][5], root;
int max(int x, int y)
void dp(int root)
}int main()
for(int i = 1; i <= n; i ++)
} dp(root);
printf("%d", max(dp[root][1], dp[root][0]));
}
樹的重心定義為,當把節點x去掉後,其最大子樹的節點個數最少(或者說成最大連通塊的節點數最少),那麼節點x就是樹的重心。
需要注意的是重心最多只有兩個,並且節點數一定小於等於總和 (原因易證)利用這些定理就可以解決啦
#include#include#includeusing namespace std;
int dp[105], tot, n, ans1, ans2;
bool flag[105];
vectorv[105];
int max(int x, int y)
int min(int x, int y)
void dp(int root)
} }if(n - dp[root] > n / 2)
if(!f)
}int main()
flag[1] = 1; dp(1);
printf("%d\n", tot);
if(tot == 1) printf("%d", ans1);
else printf("%d\n%d", min(ans1, ans2), max(ans1, ans2));
}
給定一棵樹,樹中每條邊都有乙個權值,樹中兩點之間的距離定義為連線兩點的路徑邊權之和。樹中最遠的兩個節點(兩個節點肯定都是葉子節點)之間的距離被稱為樹的直徑,連線這兩點的路徑被稱為樹的最長鏈。後者通常也可稱為直徑。
好像有很多種做法這裡就說一下樹形dp做法
求出最長的一條鏈,每次判斷更新,別忘了更新ans(用最長的鏈加上當前的鏈以及權值),最後輸出ans就可以啦
#include#includeusing namespace std;
bool flag[200005];
int dp[200005], head[200005], to[200005], next[200005], tot, ans;
int max(int x, int y)
int min(int x, int y)
void add(int x, int y)
void dp(int x)
}int main()
flag[1] = 1;
dp(1);
printf("%d", ans);
}
樹形DP簡單總結
樹的特徵 1.n個點 只有n 1條邊的無向圖 2.無向圖里 任意兩點有且只有一條路 3.乙個點只有乙個前驅 但可以有多個後繼 4.無向圖沒有環 樹形dp 由於樹有著天然的遞迴結構 父子結構 而且它作為一種特殊的圖 可以描述許多複雜的資訊 因此在樹就成了一種很適合dp的框架 問題 給你一棵樹 要求用最...
mysql的簡單介紹 mysql的簡單介紹
mysql的簡單介紹 資料庫的內部鏈結 1 連線管理器 使用者或應用程式連線 2 分析器 3 快取區4 優化器 優化器執行的結果交由儲存引擎,再轉向物理層 表空間 myisam每個表有三個檔案 frm 表結構 myd 表資料 myi 表索引 innodb 所有表空間再乙個檔案 資料庫失敗的原因 1 ...
xgboost簡單介紹 xgboost介紹
xgboost是華盛頓大學博士陳天奇創造的乙個梯度提公升 gradient boosting 的開源框架。至今可以算是各種資料比賽中的大殺器,被大家廣泛地運用。接下來,就簡單介紹一下xgboost和普通的gbdt相比,有什麼不同。何為gradient boosting,gbdt請看我上篇文章 1.梯...