Game

【原题链接】

【题意说明】
  
一棵树有n个结点,n-1条边,每个结点有个权值。每次可以获得从根节点走到叶子结点所有结点的权值和,但是每个结点的权值只能使用一次。求走k次所能获得的最大权值和。

【问题分析】
  
dfs1求出所有所有点重儿子(以权值和大小划分),dfs2保留每条重链(top点)的权值和,其它的点全部清为-1。
  然后再每个点的权值从大到小排个序,取前面的k个。
  显然每条重链都会到叶子结点。而且所取的K条重链也都可以走到(即前K个依次取,都能按题意要求从1开始到达每条重链的叶子结点)。

【参考代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define to(i) edge[i].to
#define nx(i) edge[i].next
#define sz(i) sum[i]
#define hd(i) node[i].head
#define vl(i) node[i].value
#define sn(i) node[i].son
#define tp(i) node[i].top
#define id(i) node[i].index
#define ll long long
const int maxN=100010;
struct Edge{
       int to, next;
}edge[maxN];
struct Node{
       int head, value, son, top, index;
}node[maxN];
ll sum[maxN];

int n, k, t;
void init();
void work(int);
void dfs1(int);
void dfs2(int, int);
void addedge(int, int, int);
int main(){
       scanf("%d", &t);
       for(int i=0; i<t; i++){
              init();
              work(i+1);
       }
       return 0;
}
void init(){
       memset(sum, 0, sizeof(sum));
       memset(node, 0, sizeof(node));
       memset(edge, 0, sizeof(edge));
       scanf("%d%d", &n, &k);
       for(int i=1; i<=n; i++) scanf("%d", &vl(i));
       for(int i=1; i<n; i++){
              int x, y;
              scanf("%d%d", &x, &y);
              addedge(x, y, i);
       }
       dfs1(1);
       dfs2(1, 1);
}
void addedge(int x, int y, int k){
       to(k)=y; nx(k)=hd(x); hd(x)=k;
}
void dfs1(int k){
       sz(k)=vl(k);
       for(int i=hd(k); i; i=nx(i)){
              if(sz(to(i))) return;
              dfs1(to(i));
              if(sz(sn(k))<sz(to(i))) sn(k)=to(i);
              sz(k)=sz(sn(k))+vl(k);
       }
}
void dfs2(int k, int _tp){
       id(k)=1;
       if(k!=_tp) sz(k)=0;
       if(sn(k)) dfs2(sn(k), _tp);
       for(int i=hd(k); i; i=nx(i))
              if(!id(to(i))) dfs2(to(i), to(i));
}
void work(int t){
       sort(sum+1, sum+n+1);
       int i=n; ll total=0;
       while(k&&sz(i)>0){
              total+=sz(i);
              i--; k--;
       }
       printf("Case #%d: %I64d ", t, total);
}

 

原文地址:https://www.cnblogs.com/ahmasoi/p/6678542.html