題目描述
給一棵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 有邊相連。
輸出格式:
僅乙個數,即著色結點數的最小值。
由題意可反應到應該是樹形動歸。
先考慮乙個父節點和乙個子節點。 若子節點的顏色和父節點相同, 那我們子節點不染色,撤銷子節點的顏色, 顯然不造成影響。弱父節點與子節點顏色不一樣, 兩個點都染色即可。
擴充套件到多個子節點顯然也成立, 即遵照:同色 - 1,異色不變即可
所以歸納一下, 無論如何, 我們在討論的這個父節點總要在這一步染色, (在以後會不會把顏色撤銷還不知道), 所以我們用兩個陣列 \(dp[i][2]\) 來表示第 \(i\) 號點分別染黑色、白色的最少用點數。 此時分類討論, 有狀態轉移方程: $$dp[u][0] = 1 + \sum \min(dp[v][0] - 1,dp[v][1])$$$$dp[u][1] = 1 + \sum \min(dp[v][1] - 1,dp[v][0])$$
邊界顯然在葉子節點: 對於有需要的節點, 染成需要顏色則為 \(1\) ,不需要顏色賦值為無窮大以排除影響。 其他節點因為在動歸本次時會加乙個 \(1\) ,故不是葉子節點時自己加上 \(1\) 。
p.s. 當然我們需要判斷一下此點的兒子是否有需要顏色, 若所有子節點都沒有需要, 則將自己置為 \(0\) 這題資料較水加上偷點小懶, 這裡就不特判啦
#include#include#include#include#includeusing namespace std;
int rd()
while(c >= '0' && c <= '9')
return flag * out;
}const int maxn = 1000019, inf = 1e9 + 19;
int head[maxn], nume = 1;
struct nodee[maxn << 3];
void add(int u, int v, int dis)
int num, na;
int dp[maxn][2];
int root;
void dfs(int u, int f)
if(flag)dp[u][0]++, dp[u][1]++;
}int main()
for(int i = 1;i <= num - 1;i++)
root = na + 1;
dfs(root, -1);
int ans = min(dp[root][0], dp[root][1]);
printf("%d\n", ans);
return 0;
}
P3155 CQOI2009 葉子的染色
能自己寫出來一篇 並且ac,感覺真不錯 其實我覺得都不用怎麼解釋了 給出定義 f x y 表示把節點 x 染色為 y 在以 x 為根的子樹裡最少需要染的點的數量。注意一下轉移方程,不明白的自己畫個圖推一推,推不出來的再看看定義,在這裡就不解釋了。實在不明白一號機位歡迎你 這道題我第三次才過 第一次r...
CQOI2009 葉子的染色
首先,選擇任意乙個度數大於 1 的節點為根的最優的答案都是固定的,具體證明這裡不加贅述。我們仔細研究,他只要求根節點到葉子節點的最後乙個有色節點的顏色。我們對第 x 號節點染色,意味著我們把所有它子樹中的葉子節點最近的乙個有色節點的顏色就發生了改變。顯然,兒子越多的節點價效比越高。因此,我們定義 d...
1304 CQOI2009 葉子的染色
原博主部落格 time limit 10 sec memory limit 162 mb description 給一棵m個結點的無根樹,你可以選擇乙個度數大於1的結點作為根,然後給一些結點 根 內部結點和葉子均可 著以黑色或白色。你的著色方案應該保證根結點到每個葉子的簡單路徑上都至少包含乙個有色結...