hdu 6060 RXD and dividing (树 + 贪心)

来源:互联网 发布:mac系统还原 编辑:程序博客网 时间:2024/05/17 08:14

解题思路:考虑每一条边权在最大花费中的贡献,因为最多有k个点集,所以一条边最多被统计k次,每条边被统计的次数跟这条边下端节点这棵子树的大小有关,因为这棵子树上的每个点都可以分到不同的k个集合,能分出去多少点就会被统计几次。

AC代码:

/*    @Author: wchhlbt    @Date:   2017/8/2*/#include <bits/stdc++.h>#define Fori(x) for(int i=0;i<x;i++)#define Forj(x) for(int j=0;j<x;j++)#define maxn 1000007#define inf 0x3f3f3f3f#define ONES(x) __builtin_popcount(x)#define _  << "  " <<using namespace std;typedef long long ll ;const double eps =1e-8;const int mod = 1000000007;typedef pair<int, int> P;const double PI = acos(-1.0);int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0};inline int read(){ int num;    scanf("%d",&num);   return num;}vector<P> e[maxn];int n,k;ll ans = 0;ll siz[maxn];void dfs(int u, int fa, int val){    siz[u] = 1;    for(int i = 0; i<e[u].size(); i++){        int v = e[u][i].first;        int vval = e[u][i].second;        if(v==fa)   continue;        dfs(v,u,vval);        siz[u] += siz[v];    }    if(siz[u]>=k)        ans += 1ll*val*k;    else        ans += siz[u]*val;}int main(){    //freopen("1003.in","r",stdin);    //freopen("output.txt","w",stdout);    while(~scanf("%d%d",&n,&k)){        ans = 0;        for(int i = 1; i<=n; i++)            e[i].clear();        for(int i = 1; i<n; i++){            int u,v,val;            scanf("%d%d%d",&u,&v,&val);            e[u].push_back(make_pair(v,val));            e[v].push_back(make_pair(u,val));        }        dfs(1,-1,0);        printf("%lld\n",ans);    }    return 0;}/*unsigned   int   0~4294967295int   2147483648~2147483647unsigned long 0~4294967295long   2147483648~2147483647long long的最大值:9223372036854775807long long的最小值:-9223372036854775808unsigned long long的最大值:18446744073709551615__int64的最大值:9223372036854775807__int64的最小值:-9223372036854775808unsigned __int64的最大值:18446744073709551615*/


原创粉丝点击