• HDU 5242 Game(贪心)


    http://acm.hdu.edu.cn/showproblem.php?pid=5242

    题意:

    给出一棵树,每个节点都有一个权值,每次可以获得从根结点(1)到叶子节点上的所有权值和,每个节点只能获得一次。求k次操作后可以获得的最大权值和。

    思路:

    反向建图,首先求出所有节点到根节点的权值和,然后降序排序,从可以获得最大权值和的叶子节点开始计算。已经遍历过的节点就直接返回0。计算完后再次重新排序,取前面的k个较大值。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<cstring>
     5 using namespace std;
     6 const int maxn = 1e5+5;
     7 typedef long long ll;
     8 int tot, n, k;
     9 ll val[maxn],head[maxn];
    10 bool vis[maxn];
    11 
    12 struct node
    13 {
    14     int v,next;
    15 }e[maxn];
    16 
    17 struct Node
    18 {
    19     int id;
    20     ll sum;
    21     bool operator< (const Node& rhs)const
    22     {
    23         return sum>rhs.sum;
    24     }
    25 }t[maxn];
    26 
    27 void addEdge(int u, int v)
    28 {
    29     e[tot].v = v;
    30     e[tot].next = head[u];
    31     head[u] = tot++;
    32 }
    33 
    34 ll dfs1(int u)
    35 {
    36     if(vis[u])  return t[u].sum;
    37     vis[u] = true;
    38     t[u].sum = val[u];
    39     for(int i=head[u];i!=-1;i=e[i].next)
    40     {
    41         int v = e[i].v;
    42         t[u].sum += dfs1(v);
    43     }
    44     return t[u].sum;
    45 }
    46 
    47 ll dfs2(int u)
    48 {
    49     if(vis[u])  return 0;
    50     vis[u] = true;
    51     ll tmp = val[u];
    52     for(int i=head[u];i!=-1;i=e[i].next)
    53     {
    54         int v = e[i].v;
    55         tmp += dfs2(v);
    56     }
    57     return tmp;
    58 }
    59 
    60 int main()
    61 {
    62     //freopen("in.txt","r",stdin);
    63     int T;
    64     int cas = 0;
    65     scanf("%d",&T);
    66     while(T--)
    67     {
    68         tot = 0;
    69         memset(head,-1,sizeof(head));
    70         scanf("%d%d",&n,&k);
    71         for(int i=1;i<=n;i++)  scanf("%lld",&val[i]);
    72         for(int i=1;i<n;i++)
    73         {
    74             int u,v;
    75             scanf("%d%d",&u,&v);
    76             addEdge(v,u);
    77         }
    78         memset(vis,0,sizeof(vis));
    79         memset(t,0,sizeof(t));
    80         for(int i=1;i<=n;i++)
    81         {
    82             t[i].id = i;
    83             t[i].sum = dfs1(i);
    84         }
    85         sort(t+1,t+n+1);
    86         memset(vis,0,sizeof(vis));
    87         for(int i=1;i<=n;i++)
    88         {
    89             int root = t[i].id;
    90             t[i].sum = dfs2(root);
    91         }
    92         sort(t+1,t+n+1);
    93         ll ans = 0;
    94         for(int i=1;i<=k;i++)
    95             ans += t[i].sum;
    96         printf("Case #%d: %lld
    ",++cas,ans);
    97     }
    98     return 0;
    99 }
  • 相关阅读:
    可编辑多行列表框
    NullableComboBox
    灵活的组合框和编辑控件
    EmrColorComboBox
    Java 中基本类型和字符串之间的转换
    Java 中基本类型和字符串之间的转换
    数据结构实验之排序七:选课名单
    数据结构实验之排序七:选课名单
    数据结构实验之排序四:寻找大富翁
    数据结构实验之排序四:寻找大富翁
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/9258562.html
Copyright © 2020-2023  润新知