zoukankan      html  css  js  c++  java
  • [CQOI2009]叶子的染色

    首先,选择任意一个度数大于(1)的节点为根的最优的答案都是固定的,具体证明这里不加赘述。

    我们仔细研究,他只要求根节点到叶子节点的最后一个有色节点的颜色。我们对第(x)号节点染色,意味着我们把所有它子树中的叶子节点最近的一个有色节点的颜色就发生了改变。显然,儿子越多的节点性价比越高。

    因此,我们定义(dp_{i,0/1})为第(i)号节点染成第(j)种颜色的最小花费,那么对于(j)号节点是他的儿子,可以把他的儿子染成异色,也可以让儿子的颜色与他一致,有转移方程如下:

    (dp_{i,0}) += (min(dp_{j,0} - 1 , dp_{j,1}))

    (dp_{i,1}) += (min(dp_{j,1} - 1 , dp_{j,0}))

    ```cpp
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int MAXN = 1e4 + 5;
    int head[MAXN] , to[MAXN << 1] , nxt[MAXN << 1] , cnt , n , m;
    int c[MAXN] , dp[MAXN][2];
    void add(int x , int y){nxt[++cnt] = head[x];head[x] = cnt;to[cnt] = y;}
    void read(int &x) {
    	int f = 1;x = 0;char s = getchar();
    	while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();}
    	while(s >= '0' && s <= '9') {x = (x << 3) + (x << 1) + s - '0';s = getchar();}
    	x *= f;
    }
    void dfs(int x , int fa) {
    	if(x <= n) {
    		dp[x][c[x]] = 1; // 染上的花费
    		dp[x][!c[x]] = 1e9; // 不能染这种颜色,设为无穷大
    		return;
    	}
    	dp[x][0] = dp[x][1] = 1;
    	for (int i = head[x]; i; i = nxt[i]) {
    		if(to[i] == fa) continue;
    		dfs(to[i] , x);
    		dp[x][0] += min(dp[to[i]][0] - 1 , dp[to[i]][1]);
    		dp[x][1] += min(dp[to[i]][0] , dp[to[i]][1] - 1);
    		//转移,如上
        }
    }
    int main() {
    	read(m);read(n);
    	for (int i = 1; i <= n; ++i) read(c[i]);
    	for (int i = 1; i < m; ++i) {
    		int x , y;
    		read(x);read(y);
    		add(x , y);
    		add(y , x);
    	}
    	dfs(m , m);//姑且选m为根节点
    	printf("%d" , min(dp[m][0] , dp[m][1]));
    	return 0;
    }
    
    ```
  • 相关阅读:
    CODEVS——T 2618 核电站问题
    Spring使用AspectJ注解和XML配置实现AOP
    oracle存储过程
    oracle什么时候需要commit
    短信发送接口被恶意访问
    JAVA内存模型
    构造函数,静态代码块,构造代码块
    mybatis缓存
    volatile和synchronized
    利用反射创建对象必须要显式的声明构造方法吗?
  • 原文地址:https://www.cnblogs.com/Reanap/p/13423244.html
Copyright © 2011-2022 走看看