動態規劃 換根DP

2022-05-11 05:53:25 字數 979 閱讀 1719

設 \(f[u]\) 為以1為根時,u節點的子樹中的答案。

設 \(g[u]\) 為以1為根時,u節點向父親p方向看,包括父親p但不包括u節點的子樹中的答案。

則答案為 \(f[u]+g[u]\)

當維護g的運算是乙個群時,可以直接用逆運算去掉當前節點u的貢獻。

void dfs1(int u, int p) 

}void dfs2(int u, int p)

for(int &v : g[u])

}

當維護的運算是不存在逆元的半群時,要用奇奇怪怪的方法計算。例如假如是要求最大值,那麼就維護第1大和第2大。

struct max2 

// insert value v

void insert(int v)

}// remove value v and query max

int removemax(int v)

};

題意:給一棵樹,對於每個點,問是否可以在(你自己想要怎麼操作就怎麼操作)一次操作之後使得刪去這個點之後剩下的連通塊的大小都不超過n/2。操作為刪除一條邊然後加上一條邊,並保證操作之後仍然是一棵樹。

題解:設siz[u]為以1為根時,子樹的siz。設 x[u] 為 以 u 為根時,最大的子樹的siz,設y1[u] 為以 1為根時,u節點內的不超過n/2的最大的子樹的siz,設 y2[u] 為從以 1 為根換到以u為根時,從u節點方向往下看,看到p節點內的不超過n/2的最大的子樹的siz。答案為x[u]<=n/2,或者以u為根時,那棵唯一的最大的子樹減去其不超過n/2的最大的子樹(並把這個子樹直接連線到u上面)之後的siz不超過n/2。

麻煩的是y2[u],y2[u]=n-siz[u]\leq n/2 ? n-siz[u] : max(y2[p],\max_y1[v]) ,後面這個遍歷p節點的子樹的所有y1[v],然後除去y1[u]之後的最大值,需要用上面的max2資料結構來維護。

樹形 dp 換根 dp

樹形dp 樹形動歸一般是依賴於dfs的,根據動歸的後效性,父節點的狀態一般都依賴子節點的狀態以某種方式轉移而來 換根的p2015 設f i j 表示i的子樹上保留j條邊最多蘋果數 p2279 狀態表示f x 0 覆蓋到x的爺爺和x整棵子樹 向上2層 最少個數 f x 1 覆蓋到x的父親和x子樹 向上...

樹形DP 換根DP

某些樹形dp問題中,我們要求的值是類似 以當前節點為根節點得到的答案 卻沒有給出固定的根節點,若仍然按照常規的樹形dp思路對每個點進行dp,我們對每乙個節點均進行一次 dfs 最後的複雜度是 o left n 2 right 如果我們先假設任意乙個點為根進行 dp,求出當前樹形結構下以每個點為根的子...

換根dp入門

本題是要你任選乙個點為根使得樹上的所有點深度之和最小。本題是要你任選乙個點為根使得樹上的所有點深度之和最小。首先考慮如果是指定根節點你會不會做 已知根節點的話,我們只需要一遍dfs 或者bfs 就可以求出每個點的深度,然後求和就可以了。然後我們考慮如果我們知道當前節點x為根的結果能否快速求出以它某兒...