G

 题目链接:

G - Game

 HDU - 5242 

题目大意:首先是T组测试样例,给出一颗以1节点为根的树,每个节点有各自的价值,有m次从根节点出发向下走到叶子节点的机会,每次会得到所有经过节点的权值,每个节点只有在第一次经过时有价值,求m次之后能够获得的最大权值。

具体思路:数链剖分,把重链按照权值划分,当前链储存的是这条链上的总的权值。

AC代码:

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<cmath>
  4 #include<string>
  5 #include<algorithm>
  6 using namespace std;
  7 # define ll long long
  8 # define inf 0x3f3f3f3f
  9 const int maxn = 2e5+100;
 10 const int mod  = 1e9;
 11 ll val[maxn];
 12 int edgenum,dfsnum,depth[maxn];
 13 int son[maxn],father[maxn],ord[maxn];
 14 ll Size[maxn];
 15 int top[maxn];
 16 vector<int>Edge[maxn];
 17 vector<ll>sto;
 18 void init()
 19 {
 20     edgenum=0;
 21     dfsnum=0;
 22 }
 23 void dfs1(int fr,int rt,int dep)
 24 {
 25     father[fr]=rt;
 26     Size[fr]=0;
 27     son[fr]=-1;
 28     depth[fr]=dep;
 29     for(int i=0; i<Edge[fr].size(); i++)
 30     {
 31         int to=Edge[fr][i];
 32         if(to==rt)continue;
 33         dfs1(to,fr,dep+1);
 34         Size[fr]=max(Size[fr],Size[to]);
 35         if(son[fr]==-1||(Size[son[fr]]<Size[to]))
 36         {
 37             son[fr]=to;
 38         }
 39     }
 40     Size[fr]+=val[fr];// 可以手动模拟一遍dfs的过程就能明白了
 41 }
 42 void dfs2(int fr,int rt)
 43 {
 44     ord[fr]=++dfsnum;
 45     top[fr]=rt;
 46     if(son[fr]!=-1)
 47         dfs2(son[fr],rt);
 48     for(int i=0; i<Edge[fr].size(); i++)
 49     {
 50         int to=Edge[fr][i];
 51         if(son[fr]!=to&&father[fr]!=to)
 52         {
 53             dfs2(to,to);
 54         }
 55     }
 56 }
 57 int main()
 58 {
 59     int T,Case=0;
 60     scanf("%d",&T);
 61     while(T--)
 62     {
 63         dfsnum=0;
 64         int n,k;
 65         scanf("%d %d",&n,&k);
 66         for(int i=1; i<=n; i++)
 67         {
 68             scanf("%d",&val[i]);
 69             Edge[i].clear();
 70         }
 71         int st,ed;
 72         for(int i=1; i<n; i++)
 73         {
 74             scanf("%d %d",&st,&ed);
 75             Edge[st].push_back(ed);
 76            // Edge[ed].push_back(st);
 77         }
 78         dfs1(1,-1,1);
 79         dfs2(1,1);
 80         sto.clear();
 81         for(int i=1; i<=n; i++)
 82         {
 83             if(top[i]!=i)
 84                 continue;
 85             ll sum=0,pos=i;
 86             while(pos!=-1)
 87             {
 88                 sum+=(ll)val[pos];
 89                 pos=son[pos];
 90             }
 91             sto.push_back(sum);
 92         }
 93         sort(sto.begin(),sto.end());
 94         ll sum=0;
 95         int len=sto.size();
 96         for(int i=len-1; i>=max(0,len-k); i--)
 97         {
 98             sum+=sto[i];
 99         }
100         printf("Case #%d: %lld
",++Case,sum);
101     }
102     return 0;
103 }

 

原文地址:https://www.cnblogs.com/letlifestop/p/10797579.html