• 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
    ", ++Case, ans);
    83         
    84     }
    85 
    86     return 0;
    87 
    88 }
  • 相关阅读:
    设计模式之观察者模式
    设计模式之模板方法模式
    设计模式之代理模式(全面讲解)
    设计模式之工厂模式(包含三种模式)
    设计模式之单例模式(包含三种方式)
    opencv+vs2015 堆内存析构异常
    用python来压缩文件
    GPT安装ubuntu的问题
    Two Sum and add Two Numbers
    [LeetCode] Palindrome Partitioning II
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/6411216.html
Copyright © 2020-2023  润新知