樹形dp之換根dp
換根dp是樹形dp這一類中我覺得比較難的一類。
一般的樹形dp都只需要從子樹往父親推,然而換根dp則需要從父親往子樹推,接下來寫寫我學習換根dp的幾個例題。
例題1 computer
題目大意:給你一棵樹,然後問你每乙個點具體其他點最遠的距離是多少。
解題:這個題目首先任意找乙個點為根節點,然後求出這個點的最遠距離,除了這個最遠距離之外,還需要存乙個次遠距離,這是第乙個dfs。第二個dfs就比較重要了,這個才是換根dp的精髓,對於乙個節點從父親節點推過來,如果該節點是父親節點最長鏈的一環,那麼這個節點只能從父親節點的次大值更新(值得注意的是,我們開始求最大值和次大值的同時就應該保證了最大值和次大值不是同一條鏈),如果不是最長鏈的一環,那麼直接可以從父親節點的最大值更新。
#include#include#include#include#include#include#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e5+7;
const int mod=1e9+7;
int head[maxn],cnt;
struct node
}e[maxn*2];
void add(int u,int v,ll w)
ll dp1[maxn],dp2[maxn];
ll dfs1(int u,int pre)
else res2=max(res2,f);
} dp1[u]=res1,dp2[u]=res2;
return res1;
}void dfs2(int u,int pre)
else dp2[v]=max(dp2[v],dp2[u]+e[i].w);
} else
else dp2[v]=max(dp2[v],dp1[u]+e[i].w);
} dfs2(v,u); }}
int main()
dfs1(1,0);
dfs2(1,0);
for(int i=1;i<=n;i++) printf("%lld\n",dp1[i]);
} return 0;
}
例2 湖南2019省賽2019
題目大意:給你一棵樹,樹的每一條邊都有乙個邊權值,然後問,任意兩個節點之間的距離是2019的偶數倍,這樣的節點對數有多少,提示(u,v)和(v,u)是一樣的。
這個題目我也是用換根dp求的,dp[ u ] [ i ] 表示以節點u為乙個端點,u到其他節點的距離對2019取模為i的路徑數。
所以按照換根dp的套路,第乙個dfs求以1為根節點的路徑數量,第二個dfs由父親向兒子轉移,求出兒子的dp。
這裡有乙個地方要很注意,這個我在**中強調了。
#include#include#include#include#include#include#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=2e4+7;
const int mod=2019;
int head[maxn],cnt;
struct node
}e[maxn*2];
void add(int u,int v,int w)
ll dp[maxn][2022],ans=0,num[2022];
void dfs2(int u,int pre) }}
void dfs3(int u,int pre)
ans+=dp[u][0];
}void init(int n)
int main()
dfs2(1,0),dfs3(1,0);
printf("%lld\n",ans/2);
} return 0;
}
樹形 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,求出當前樹形結構下以每個點為根的子...
E Tree Painting 樹形dp 換根
題意 給定一棵樹,一開始點都是白色的,每次你可以對乙個點染色,獲得的分數就是當前點連線的只含白色的點的連通塊的點個數。輸出最多的分數。2 n 2 1 05 2 n 2 10 5 2 n 2 105分析 每次對乙個點進行操作就將樹分成了m棵子樹,並且我們肯定是先操作父節點,再操作子節點,所以自然就想到...