[树形dp] Jzoj P1010 叶子的颜色
Posted comfortable
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[树形dp] Jzoj P1010 叶子的颜色相关的知识,希望对你有一定的参考价值。
题解
- 其实这题一直在纠结选哪个作根
- 其实知道根后,就是一个典型的树形dp
- 设f[i][0/1]为以i为根的子树i点染0/1色的最少染色点数
- 那么叶子的点的初始值就是要染的颜色为1不染的INF
- 现在考虑一下选哪个为根
- 现在我们不知道根节点是什么?换根么?再仔细思考一下...其实可以证明无论选择谁做根结点都是一样的
(其实换根也是可做滴!!)
- 因为对于两个相邻的点,首先这两个点颜色不可能相同,如果相同就不满足最小染色点数
- 如果不相同,换了也好像没有关系......
- 再感性理解一波,选一个不是叶子的结点做根的答案都是一样的
代码
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 const int inf=1000000000; 5 int n,m,c[100010],f[100010][2],to[200010],from[200010],head[100010],cnt; 6 void insert(int x,int y) { to[++cnt]=y; from[cnt]=head[x]; head[x]=cnt; } 7 void dp(int root,int fa) 8 { 9 f[root][0]=f[root][1]=1; 10 if (root<=m) if (c[root]) f[root][0]=inf; else f[root][1]=inf; 11 for (int i=head[root];i;i=from[i]) 12 if (to[i]!=fa) 13 { 14 dp(to[i],root); 15 f[root][0]+=min(f[to[i]][0]-1,f[to[i]][1]); 16 f[root][1]+=min(f[to[i]][1]-1,f[to[i]][0]); 17 } 18 } 19 int main() 20 { 21 scanf("%d%d",&n,&m); 22 for (int i=1;i<=m;i++) scanf("%d",&c[i]); 23 for (int i=1;i<=n-1;i++) 24 { 25 int x,y; 26 scanf("%d%d",&x,&y); 27 insert(x,y); 28 insert(y,x); 29 } 30 dp(m+1,-1); 31 printf("%d",min(f[m+1][1],f[m+1][0])); 32 return 0; 33 }
以上是关于[树形dp] Jzoj P1010 叶子的颜色的主要内容,如果未能解决你的问题,请参考以下文章