描述
給定一顆樹(邊權為1),選取乙個節點子集,使得該集合中任意兩個節點之間的距離都大於k。求這個集合節點最多是多少
輸入第一行是兩個整數n,k
接下來是n-1行,每行2個整數x,y,表示x與y有一條邊
輸出1個整數表示最多的節點數
樣例輸入
3 1
1 2
1 3樣例輸出
提示測試點
n的上限k特徵
11512
10001鏈
3100014
1000001鏈
510000016
152710002鏈
8100029
1000002鏈
101000002
樹形dp入門題。
t=2的情況有點意思。
設當前訪問第i個節點。 f[
i][0
] f[i
][0]
:i不選但i父親選。 f[
i][1
] f[i
][1]
:不選且i父親不選。 f[
i][2
] f[i
][2]
:i選。
顯然有: f[
i][2
]=1+
∑vf[
v][0
] f[i
][2]
=1+∑
vf[v
][0]
以及: f[
i][0
]=∑v
f[v]
[1] f[i
][0]
=∑vf
[v][
1]
關鍵是f[
i][1
] f[i
][1]
這個東西需要考慮兒子之間是否衝突,因此最優值的產生有兩種可能:
1. 所有兒子都不選。
2. 某乙個兒子選,其餘不選。
因此有f[i
][1]
=(∑v
f[v]
[1])
+max
(0,f
[v][
2]−f
[v][
1]) f[i
][1]
=(∑v
f[v]
[1])
+max
(0,f
[v][
2]−f
[v][
1])。
**:
#include
#define n 100005
using
namespace
std;
inline
int read()
int first[n],n,k,cnt=0,f[n][3];
struct edgee[n<<1];
inline
void add(int u,int v)
inline
int max(int a,int b)
inline
int dfs1(int p,bool k,int fa)
return f[p][k];
}inline
int dfs2(int p,int k,int fa)
}else
if(k==1)
return f[p][k];
}int main()
memset(f,-1,sizeof(f));
if(k==1)cout
<1,1,1),dfs1(1,0,1));
else
cout
<1,1,1),dfs2(1,2,1));
return
0;}
bzoj 4316 小C的獨立集 樹形dp
仙人掌樹形dp。令f x 0 表示以x為根的子樹中,不選x的最大值 f x 1 表示選x的最大值。注意到,同乙個環中的所有點,只有在dfs樹中最高的那個點才會對所在環之外的點的f值造成影響。因此我們在最高的那個點做乙個dp,然後就得到了最高那個點的f,而這個環中的其他點的f就不用管了。ac 如下 i...
樹形DP 樹形DP四例
是時候練一下dp了!我的題單 portkey f u,if fu,i 表示以u uu為根節點的子樹中保留i ii條樹枝的最大蘋果數 f u,i max f max f fu,i max這些題是菜,但也不能輕視啊!include using namespace std define in read i...
HLOJ 樹形DP前置 DFS(樹形DP入門)
給定一棵 n nn 個點的樹,根為 t tt求每個點的父親是哪個點,t tt 的父親輸出 0 00第一行兩個整數 n,t n,tn,t接下來 n 1 n 1n 1 行,每行兩個整數 x,y x,yx,y,表示 x,y x,yx,y 之間有一條邊 n nn 行,第 i ii 行乙個整數,表示 i ii...