HDU 5242 Game(树上贪心)

题目链接 Game

题目的意思很简单, 就是要找一棵树权值最大等等前K条链。

在本题中,走的次数等于min(叶子结点个数,k)

tree[i].sum意为从i号结点出发走到某个叶子结点能得到的最大总价值。

pson[i]表示i号结点若要获得最大价值那么下一步该怎么走。

显然tree[i].sum和pson[i]是从i的各个儿子转移得到的。

那么先做一遍DFS计算出tree[i].sum, 再排序。

然后贪心,从价值最大的那个结点开始选,从大到小。

选的时候,要把他中途经过的结点全部屏蔽(就是说被屏蔽的结点接下来不能被选了)。

当选的次数到达k或者没有结点可选时那就停止。

具体可以看我的代码。

 

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define REP(i,n)                for(int i(0); i <  (n); ++i)
 6 #define rep(i,a,b)              for(int i(a); i <= (b); ++i)
 7 #define dec(i,a,b)              for(int i(a); i >= (b); --i)
 8 #define for_edge(i,x)           for(int i = H[x]; i; i = X[i])
 9 
10 #define LL      long long
11 
12 const int N     =    100000      +       10;
13 const int M     =    10000       +       10;
14 const int A     =    30          +       1;
15 
16 struct Node{
17     LL sum; int id;
18     friend bool operator < (const Node &a, Node &b){
19         return a.sum > b.sum;
20     }
21 } tree[N];
22 
23 int E[N << 2], X[N << 2], H[N << 2], pson[N];
24 bool isleaf[N], v[N], vc[N];
25 LL a[N], c[N], ans;
26 int T, n, k, et, x, y, num;
27 int Case = 0;
28 int cnt = 0;
29 
30 bool cmp(LL a, LL b){ return a > b;}
31 
32 inline void addedge(int a, int b){
33     E[++et] = b, X[et] = H[a], H[a] = et;
34 }
35 
36 void dfs(int x, int fa){
37     LL cnt = 0, tot = 0, w = 0;
38     tree[x].sum = a[x];
39     for_edge(i, x) if (E[i] != fa){
40         int u = E[i]; ++cnt;
41         dfs(u, x);
42         if (tree[u].sum > tot){ tot = tree[u].sum; w = u;}    
43     }
44     pson[x] = w;
45     if (cnt == 0)  isleaf[x] = true;    
46     else tree[x].sum += tree[w].sum;
47 }
48         
49 void tag(int x){
50     v[x] = false;
51     if (!isleaf[x]) tag(pson[x]);
52 }
53 
54 int main(){
55 
56     scanf("%d", &T);
57     while (T--){
58         et = 0; num = 0;
59         scanf("%d%d", &n, &k);
60         memset(H, 0, sizeof H);
61         memset(c, 0, sizeof c);
62         memset(pson, 0, sizeof pson);
63         memset(vc, false, sizeof vc);
64         memset(isleaf, false, sizeof isleaf);
65         rep(i, 1, n) scanf("%lld", a + i);
66         rep(i, 1, n - 1){
67             scanf("%d%d", &x, &y);
68             addedge(x, y); addedge(y, x);
69             vc[y] = true;
70         }
71         rep(i, 1, n) tree[i].id = i;
72         dfs(1, 0);
73         sort(tree + 1, tree + n + 1);
74         memset(v, true, sizeof v);
75         cnt = 0; ans = 0;
76         rep(i, 1, n) if (v[tree[i].id] && cnt < k){
77             ans += tree[i].sum;
78             tag(tree[i].id);
79             ++cnt;
80         }
81 
82         printf("Case #%d: %lld\n", ++Case, ans);
83         
84     }
85 
86     return 0;
87 
88 }

 

posted @ 2017-02-17 18:56  cxhscst2  阅读(161)  评论(0编辑  收藏  举报