• Gym102460B The Power Monitor System(树形dp)


    当不存在没有被染色的边时: 若被自己染黑,则由于规则 1,这个点染了以后所有儿子都会被染 色,因此儿子的情况可以随便选:

    fu,1,0 = 1 + ∑min{fv,0/1/2,0/1}

    若被儿子染黑,则必须要选择一个儿子传递上去,儿子能传递上 来只有两种情况: fu,0,0 = minv{min{fv,0,0, fv,1,0} + ∑ v ′̸=v min{fv,0,0, fv,0,1, fv,1,0}}

    若只被父亲染黑,则儿子不能把 u 染黑,为了 u 和儿子之间的边 能够被覆盖,只能用规则 2,发现只有一种情况:fu,2,0 = ∑fv,0,1

    当与儿子的边中存在一条没有被染色时: 若被儿子染黑,那么要在上面的 fu,0,0 中转移式的 v ′ 中再抽出一 个 v ′′,这个 v ′′ 的贡献只能是 min{fv ′′ ,2,0/1}

    若只被父亲染黑,同理,在上面的 fu,2,0 中转移式的 v 中抽出一个 v ′,这个 v ′ 的贡献也只能是 min{fv ′ ,2,0/1}

    时间复杂度 O(n)。

    存在一条没有被染色的提取出来的代价的意义是,我们定义的状态f[u][2][1]是u与儿子在一条边没被染色,这条边因为规则4,其他边都被染色的情况下染色的状态,因此我们需要提取出这个信息。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=4e5+10;
    const int inf=0x3f3f3f3f;
    ll f[N][3][3];
    int h[N],ne[N],e[N],idx;
    int in[N];
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    void dfs(int u,int fa){
        f[u][1][0]=1,f[u][2][0]=0;
        if(in[u]==1&&fa!=-1)
            return ;
        f[u][0][0]=f[u][0][1]=f[u][2][0]=f[u][2][1]=0;
        ll g[2]={0,inf};
        ll tmp[2][2]={0,inf,inf,inf};
        for(int i=h[u];i!=-1;i=ne[i]){
            int v=e[i];
            if(v==fa)
                continue;
            dfs(v,u);
            ll tmp1=min(f[v][1][0],min(f[v][0][1],f[v][0][0]));
            g[1]=min(g[1]+tmp1,g[0]+min(f[v][1][0],f[v][0][0]));
            g[0]+=tmp1;
            tmp[1][1]=min(tmp[1][1]+tmp1,min(tmp[0][1]+min(f[v][1][0],f[v][0][0]),tmp[1][0]+min(f[v][2][1],f[v][2][0])));
            tmp[1][0]=min(tmp[1][0]+tmp1,tmp[0][0]+min(f[v][1][0],f[v][0][0]));
            tmp[0][1]=min(tmp[0][1]+tmp1,tmp[0][0]+min(f[v][2][1],f[v][2][0]));
            tmp[0][0]+=tmp1;
            f[u][1][0]+=min(f[v][1][0],min(f[v][0][0],min(f[v][0][1],min(f[v][2][0],f[v][2][1]))));
            f[u][2][1]=min(f[u][2][0]+min(f[v][2][1],f[v][2][0]),f[u][2][1]+f[v][0][1]);
            f[u][2][0]+=f[v][0][1];
        }
        f[u][0][0]=g[1];
        f[u][0][1]=tmp[1][1];
    }
    int main(){
        ios::sync_with_stdio(false);
        memset(h,-1,sizeof h);
        int n;
        cin>>n;
        for(int i=1;i<=n;i++){
            for(int j=0;j<3;j++){
                for(int k=0;k<2;k++)
                    f[i][j][k]=0x3f3f3f3f;
            }
        }
        for(int i=1;i<n;i++){
            int a,b;
            cin>>a>>b;
            add(a,b);
            add(b,a);
            in[a]++;
            in[b]++;
        }
        dfs(1,-1);
        cout<<min(f[1][1][0],min(f[1][0][0],f[1][0][1]))<<endl;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    IOS开发之SWIFT进阶部分
    Xcode7如何进行真机测试
    IOS中如果使用RGB实现背景色
    C中的基本数据类型和变量
    ActiveMQ学习笔记(20)----Consumer高级特性(二)
    ActiveMQ学习笔记(19)----Consumer高级特性(一)
    ActiveMQ学习笔记(18)----Message高级特性(二)
    ActiveMQ学习笔记(17)----Message高级特性(一)
    ActiveMQ学习笔记(16)----Message Dispatch高级特性(二)
    ActiveMQ学习笔记(15)----Message Dispatch高级特性(一)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13780765.html
Copyright © 2020-2023  润新知