CodeForces - 1466D T - 13th Labour of Heracles(贪心)

题意:

给出一棵树,定义 k − c o l o r i n g k-coloring kcoloring 为给每条边涂上 [ 1 , k ] [1,k] [1k] 的颜色,颜色不一定都用。

每个颜色的权值为去掉其他颜色后的子图中,点权和最大的连通图,定义 k − c o l o r i n g k-coloring kcoloring 的权值为每个颜色的权值之和。

k k k [ 1 , n − 1 ] [1,n-1] [1,n1] 的权值。

题解:

假设在计算颜色 i i i 的权值时,有多个连通块,因为只取点权和最大的,那么就会使其他连通块就不计入贡献,导致浪费。

所以每个颜色只需一个连通块即可。

k = 1 k=1 k=1 时,此时每条边都为1,答案为每个点的点权 s u m sum sum

k = 2 k=2 k=2时,根据以上结论,只需将这棵树一分为二即可,假设分割点为点 i i i ,答案就会变为 s u m + w [ i ] sum+w[i] sum+w[i]

k = 3 k=3 k=3时,再分割出一个连通块,答案变为 s u m + w [ i ] + w [ j ] sum+w[i]+w[j] sum+w[i]+w[j]

贪心的分割,即每次都选点权最大,且还有剩余边可以变成其他颜色的点。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int ,int > pii;
const int mod=1e9+7;
const int MAXN=1e6+5;
const int inf=0x3f3f3f3f;
int w[MAXN];
int in[MAXN];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            in[i]=0;
            scanf("%d",&w[i]);
        }
        for(int i=1;i<=n-1;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            in[u]++;in[v]++;
        }
        priority_queue<pii>q;
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            in[i]--;
            ans+=w[i];
            if(in[i])
            {
                q.push(make_pair(w[i],in[i]));
            }
        }
        printf("%lld ",ans);
        for(int i=2;i<=n-1;i++)
        {
            pii now=q.top();
            q.pop();
            ans+=now.first;
            now.second--;
            if(now.second)
            {
                q.push(now);
            }
            printf("%lld ",ans);
        }
        printf("\n");
    }
}
posted @ 2021-04-10 18:29  TheBestQAQ  阅读(43)  评论(0)    收藏  举报