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\n",ans);
    }
    return 0;
}
时间: 2024-10-26 07:25:46

hdu6060 RXD and dividing 贪心的相关文章

HDU 6060 RXD and dividing(dfs 思维)

RXD and dividing Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 1893    Accepted Submission(s): 809 Problem Description RXD has a tree T, with the size of n. Each edge has a cost.Define f(S) 

HDU 6060 17多校3 RXD and dividing(树+dfs)

Problem Description RXD has a tree T, with the size of n. Each edge has a cost.Define f(S) as the the cost of the minimal Steiner Tree of the set S on tree T. he wants to divide 2,3,4,5,6,…n into k parts S1,S2,S3,…Sk,where ?Si={2,3,…,n} and for all d

hdu 6060 RXD and dividing

思路:判断子树节点个数和k的最小值就好了,long long 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e6+10; 5 6 int n,k; 7 vector<pair<int ,ll > > e[N]; 8 ll sum; 9 int a[N]; 10 void dfs(int u,int fa){ 11 a[u]=1; 12 for

HDU 6060 RXD and dividing(LCA)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6060 [题目大意] 给一个n个节点的树,要求将2-n号节点分成k部分, 然后将每一部分加上节点1,求每个集合最小斯坦纳树的最大权值和. [题解] 我们按照后序遍历染色分组,得到的一定是最优分组, 现在考虑在不同颜色的虚树上求路径权值和, 我们发现每个点增加的权值是深度减去到根的路径上已被覆盖的长度, 这个长度等于与dfs序前继的LCA的深度,因此我们在搜索的同时计算与dfs序前继的LCA即可.

LA 4945 Free Goodies(贪心)

Description B  Free Goodies Petra and Jan have just received a box full of free goodies, and want to divide the goodies between them. However, it is not easy to do this fairly, since they both value different goodies differently. To divide the goodie

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

【uva 1615】Highway(算法效率--贪心 区间选点问题)

题意:给定平面上N个点和一个值D,要求在x轴上选出尽量少的点,使得对于给定的每个店,都有一个选出的点离它的欧几里德距离不超过D. 解法:先把问题转换成模型,把对平面的点满足条件的点在x轴的直线上可得到一个个区间,这样就是选最小的点覆盖所有的区间的问题了.我之前的一篇博文有较详细的解释:关于贪心算法的经典问题(算法效率 or 动态规划).代码实现我先空着.挖坑~

【贪心+Treap】BZOJ1691-[Usaco2007 Dec]挑剔的美食家

[题目大意] 有n头奶牛m种牧草,每种牧草有它的价格和鲜嫩度.每头奶牛要求它的牧草的鲜嫩度要不低于一个值,价格也不低于一个值.每种牧草只会被一头牛选择.问最少要多少钱? [思路] 显然的贪心,把奶牛和牧草都按照鲜嫩度由大到小排序,对于每奶牛把鲜嫩度大于它的都扔进treap,然后找出后继. 不过注意后继的概念是大于它且最小的,然而我们这里是可以等于的,所以应该是找cow[i].fresh-1的后继,注意一下…… 1 #include<iostream> 2 #include<cstdio&

POJ1017 Packets(贪心算法训练)

Time Limit: 1000MS          Memory Limit: 10000K          Total Submissions: 51306          Accepted: 17391 Description A factory produces products packed in square packets of the same height h and of the sizes 1*1, 2*2, 3*3, 4*4, 5*5, 6*6. These pro