hdu6060 RXD and dividing 贪心

/**
题目:hdu6060 RXD and dividing
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6060
题意:贪心
给定一颗树,n个节点,编号为1~n。将2~n编号的节点分成k份。
每一份分别和编号1的节点取并集。然后求每一份的节点连通的最小边权和;
然后k份获得的边权和加起来;问:求可以获得的k份边权和的总和的最大值。

思路:通过画树容易发现,假如k无穷大,如果节点x为根的子树有num个节点,那么x与x的父节点相连的那条边权最多加num次。

所以每个节点x与父节点相连的边的权值w的贡献为min(num,k)*w; num为以x为根的子树的总结点数。

*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<set>
#include<cstring>
#include<time.h>
#include<random>
#include<cmath>
using namespace std;
typedef pair<int,int> P;
typedef long long LL;
const int mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const int maxn = 1e6+100;
int n, k;
vector<P> G[maxn];
struct node
{
    int sum;
    int w;
}t[maxn];
void dfs(int r,int f)
{
    int len = G[r].size();
    t[r].sum = 1;
    for(int i = 0; i< len; i++){
        if(G[r][i].first==f) continue;
        dfs(G[r][i].first,r);
        t[G[r][i].first].w = G[r][i].second;
        t[r].sum += t[G[r][i].first].sum;
    }
}
int main()
{
    while(scanf("%d%d",&n,&k)==2)
    {
        for(int i = 1; i <= n; i++) G[i].clear();
        int u, v, w;
        for(int i = 1; i < n; i++){
            scanf("%d%d%d",&u,&v,&w);
            G[u].push_back(P(v,w));
            G[v].push_back(P(u,w));
        }
        dfs(1,-1);
        LL ans = 0;
        for(int i = 2; i <= n; i++){
            ans = (ans+(LL)min(t[i].sum,k)*t[i].w);
        }
        printf("%lld
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xiaochaoqun/p/7286990.html