【CQOI2009】叶子的颜色
Description
給一棵m個結點的無根樹,你可以選擇一個度數大于1的結點作為根,然后給一些結點(根、內部結點和葉子均可)著以黑色或白色。你的著色方案應該保證根結點到每個葉子的簡單路徑上都至少包含一個有色結點(哪怕是這個葉子本身)。
對于每個葉結點u,定義c[u]為從u到根結點的簡單路徑上第一個有色結點的顏色。給出每個c[u]的值,設計著色方案,使得著色結點的個數盡量少。
Input
第一行包含兩個正整數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 有邊相連。
Output
僅一個數,即著色結點數的最小值。
Sample Input
5 3
0
1
0
1 4
2 5
4 5
3 5
Sample Output
2
Data Constraint
Hint
【數據范圍】
1<=N,M<=100000
.
.
.
.
.
.
分析
選擇任意一個點為根,答案都是相同的。
假如原來以x為根,y與x相鄰,那么x與y的顏色不可能相同。既然顏色不同,那么將根從x變成y對答案顯然也不會產生影響。
所以隨便選一個點為根,然后樹形DP。用f[x][0/1]表示x的子樹中,最后一個點想要得到一個白色/黑色的祖先的最小代價。
.
.
.
.
.
程序:
#include<cstdio> #include<iostream> #include<cstring> #include<cmath> using namespace std; int to[100000],cnt,from[100000],head[100000],f[100000][2],n,m,inf=2147483647,c[100000]; void insert(int x,int y) { to[++cnt]=y; from[cnt]=head[x]; head[x]=cnt; } void dp(int root,int fa) { f[root][0]=f[root][1]=1; if (root<=m) if (c[root]) f[root][0]=inf; else f[root][1]=inf; for (int i=head[root];i;i=from[i]) { if (to[i]!=fa) { dp(to[i], root); f[root][0]+=min(f[to[i]][0]-1,f[to[i]][1]); f[root][1]+=min(f[to[i]][1]-1,f[to[i]][0]); } } } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) scanf("%d",&c[i]); for (int i=1;i<=n-1;i++) { int x,y; scanf("%d%d",&x,&y); insert(x,y); insert(y,x); } dp(m+1,-1); printf("%d",min(f[m+1][1],f[m+1][0])); return 0; }轉載于:https://www.cnblogs.com/YYC-0304/p/9499938.html
總結
以上是生活随笔為你收集整理的【CQOI2009】叶子的颜色的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 扑克游戏
- 下一篇: 【NOI2002】贪吃的九头龙