zoukankan      html  css  js  c++  java
  • BZOJ 1908. Pku2054 UVA1205 Color a Tree

    传送门

    看一眼感觉 $dp$,发现状态没法维护

    考虑贪心,然后就想了两个错的贪心...

    正解好神啊

    首先如果权值最大的点能够一步染色那么肯定要染它

    意思就是,一旦父节点被染色那么它就要接着被染色

    那么把它们父子两合并成一个新的点,其他节点根据原来的边也连上来

    考虑新的点的权值要怎么搞,现在既然这个节点包含了两个点,那么把它染色要两个单位时间,而染其他点只要 $1$ 单位时间

    此时染它对整颗树产生的额外的代价为 $2$ 乘其他节点权值和,把其他点 $x$ 染色额外代价为 $1$ 乘其他节点 (非 $x$ 节点) 权值和

    所以权值为原本节点权值之和除以 $2$,更大的情况也是同样处理,每次合并都计算此时合并的贡献

    贡献就是父节点大小乘子节点权值和,因为要把子节点染色得先把父节点染好,此时子节点会产生额外的代价

    这样一直合并最后只剩下根节点时答案就出来了,具体看代码吧

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<vector>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=2e5+7;
    int n,rt,val[N],sz[N],fa[N],ans;
    inline void clr() { for(int i=1;i<=n;i++) fa[i]=val[i]=sz[i]=0; ans=0; }
    void solve()
    {
        for(int i=1;i<n;i++)
        {
            int x=0,p;
            for(int j=1;j<=n;j++)
                if(j!=rt && 1.0*val[x]/sz[x]<1.0*val[j]/sz[j]) x=j;//找到权值最大的点
            p=fa[x]; ans+=sz[p]*val[x];//我们这里算的是额外的代价,不包括把本身染色的代价
            sz[p]+=sz[x]; val[p]+=val[x];
            val[x]=0; fa[x]=p;//合并
            for(int j=1;j<=n;j++)
                if(fa[j]==x) fa[j]=p;//其他点按原来关系连上来
        }
    }
    int main()
    {
        sz[0]=1;
        while(233)
        {
            n=read(),rt=read(); int a,b;
            if(!n&&!rt) break;
            for(int i=1;i<=n;i++)
                val[i]=read(),ans+=val[i],sz[i]=1;//ans初始为所有点染色本身的代价
            for(int i=1;i<n;i++) { a=read(),b=read(); fa[b]=a; }
            solve();
            printf("%d
    ",ans);
            clr();
        }
        return 0;
    }
  • 相关阅读:
    Java Object类及其常用方法
    Java 抽象类和抽象方法
    Java 多态
    Java 继承
    Java Scanner类
    正则表达_1
    「暑期集训day14」掠影
    「暑期集训day13」苦闷
    「暑期集训day12」苦楚
    「暑期集训day11」旧殤
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11408292.html
Copyright © 2011-2022 走看看