zoukankan      html  css  js  c++  java
  • 【Luogu】P3155叶子的染色(树形DP)

      题目链接

      树形DP水题qwq。

      设f[i][j]是以i为根的子树,染成j色,且满足内部需求的最少染色节点数。

      设to是x的子节点,那么状态转移方程如此设计:

      1、f[i][0]

      这个状态表示i不染色,那显然很好办,对于每个to从f[to][1],f[to][2]和f[to][0]里选一个最小的即可。

      转移方程$f[x][0]=sumlimits_{to}min(f[to][1],f[to][2],f[to][0])$

      2、f[i][1]

      此时i染成黑色。那么对于每个to我们发现,既可以让它继续染白,也可以把本来染成黑色的to改为无色,让染成黑色的i来发挥to的作用。

      于是$f[x][1]=sumlimits_{to}min(f[to][1]-1,f[to][2])$

      f[i][2]类似,不再赘述。

      

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cctype>
    #include<cstring>
    #define maxn 50020
    using namespace std;
    
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    int f[maxn][3];
    int q[maxn];
    
    struct Edge{
        int next,to;
    }edge[maxn*2];
    int head[maxn],num;
    inline void add(int from,int to){
        edge[++num]=(Edge){head[from],to};
        head[from]=num;
    }
    
    int root;
    int m,n;
    void dfs(int x,int fa){
        if(x<=n){
            f[x][q[x]+1]=1;
            f[x][(q[x]^1)+1]=f[x][0]=1000000;
            return;
        }
        int whi=0,bla=0;
        for(int i=head[x];i;i=edge[i].next){
            int to=edge[i].to;
            if(to==fa)    continue;
            dfs(to,x);
            f[x][0]+=min(f[to][1],min(f[to][2],f[to][0]));
            whi+=min(f[to][2]-1,f[to][1]);
            bla+=min(f[to][1]-1,f[to][2]);
        }
        f[x][2]=whi+1;
        f[x][1]=bla+1;
        return;
    }
            
    
    int main(){
        m=read(),n=read();
        for(int i=1;i<=n;++i)    q[i]=read();
        for(int i=1;i<m;++i){
            int from=read(),to=read();
            add(from,to);
            add(to,from);
        }
        root=n+1;
        dfs(root,root);
        printf("%d",min(f[root][0],min(f[root][1],f[root][2])));
        return 0;
    }
    
    /*
    10 5
    1 0 1 1 0
    1 6
    6 2
    6 3
    7 6
    7 4
    7 10
    10 9
    9 8
    8 5
    */
  • 相关阅读:
    Logstash
    收藏学习Linux好用的网站
    Elasticsearch
    Elasticsearch-head
    Kibana
    Metricbeat
    filebeat
    elelelleeleELK
    MySQL对库的操作
    【Django】URL控制器
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8319796.html
Copyright © 2011-2022 走看看