(題面可自行跳過)
描述
給一棵m個結點的無根樹,你可以選擇乙個度數大於1的結點作為根,然後給一些結點(根、內部結點和葉子均可)著以黑色或白色。你的著色方案應該保證根結點到每個葉子的簡單路徑上都至少包含乙個有色結點(哪怕是這個葉子本身)。
對於每個葉結點u,定義c[u]為從根結點到u的簡單路徑上最後乙個有色結點的顏色。給出每個c[u]的值,設計著色方案,使得著色結點的個數盡量少。
輸入
第一行包含兩個正整數m, n,其中n是葉子的個數,m是結點總數。結點編號為1,2,…,m,其中編號1,2,… ,n是葉子。以下n行每行乙個0或1的整數(0表示黑色,1表示白色),依次為c[1],c[2],…,c[n]。以下m-1行每行兩個整數a,b(1<=a < b <= m),表示結點a和b 有邊相連。
輸出
僅乙個數,即著色結點數的最小值
樣例輸入 [複製]
5 3010
1 42 5
4 53 5
樣例輸出 [複製]
2資料規模:
m<=10000 n<=5000
思路:本身不難,但是個人認為比較經典
狀態轉移不一定 要完全保留 子狀態 ,可以進行 改變,滿足最優性
只需要 子狀態是平行比較中最優的
首先容易想到貪心:
對於乙個有根樹,
顯然盡量向上染色能影響的節點最多。。 僅有當前節點的兒子中 不同顏色都有,就把數量少的顏色乙個個染, 數量多得作為乙個傳上去。
但是,這樣無法處理兩種顏色數量相同的情況。。
所以轉向dp
k代表顏色 (0或1) , i是當前子樹的根節點
思考狀態定義:顯然為 以i為根節點的子樹最少次數。
此題的最優子結構的染色方法肯定要改變,
所以 思考如何當前步操作,使最優子結構可以更新出當前子結構。
結合貪心,我們還是把染色點盡量上放,那麼在確定當前節點染色 (0或1),可以把染相同顏色的子節點都統一染在 當前點,總數依次-1
不同的就保留
最後所得值+1(當前要染色)
第二步:
思考換根, 對於當前根的兒子,如果有不同,僅限於這兩個結點都染色的情況。
根據貪心策略(或者狀態轉移)
顯然相鄰兩個節點顏色不相同(否則染在根上即可),那麼其中任意乙個作為根,
答案相同。
所以不需要換根。。。
//**中並沒有用陣列,直接用了pair。。還要慢一點。。。
**:
#include
#define pf printf
#define sf scanf
#define fi first
#define se second
using
namespace std;
const
int maxn=
1e4+10;
typedef pair<
int,
int> t;
vector <
int> g[maxn]
;int col[maxn]
;//f[i][k]+= min(f[son][k]-1,f[son][k^1])
inline t dfs
(int u,
int fa)
for(
int i=
0;i.size()
;++i)
ans.fi+=1
;ans.se+=1
;return ans;
}signed main (
)for
(int i=
1;i++i)
t ret=
dfs(n+1,
-1);
pf("%d"
,min
(ret.fi,ret.se));
return0;
}
樹形dp 葉子的顏色
題目描述 給一棵m個結點的無根樹,你可以選擇乙個度數大於1的結點作為根,然後給一些結點 根 內部結點和葉子均可 著以黑色或白色。你的著色方案應該保證根結點到每個葉子的簡單路徑上都至少包含乙個有色結點 哪怕是這個葉子本身 對於每個葉結點u,定義c u 為從根結點到u的簡單路徑上最後乙個有色結點的顏色。...
CQOI2009 葉子的染色 樹形dp
給一棵 m 個結點的無根樹,你可以選擇乙個度數大於 1 的結點作為根,然後給一些結點著以黑色或白色。方案應保證根結點到每個葉子的簡單路徑上都至少包含乙個有色結點。對於每個葉結點 u 定義 c u 為從根結點從 u 的簡單路徑上最後乙個有色結點的顏色。給出每個 c u 的值,設計著色方案,使得著色結點...
CQOI2009 葉子的染色 性質 樹形Dp
online judge bzoj1304,luogu p3155 label 無根樹,樹形dp 給定一棵 n 個節點的無根樹,它一共有 k 個葉子節點。你可以選擇乙個度數大於1的節點作為根,並對整棵樹進行染色 對於每個節點可以染黑 白,或選擇不染 著色方案需滿足以下約束 1.每個葉子節點到樹根的路...