• E


    https://vjudge.net/contest/299785#problem/E

    题意:给你n个点,n-1个边构成有向数,同时每个点都有一个权值,现在给你k次操作,每次操作你必须从根节点1出发,然后走到一个叶节点结束然后将它们点的权值累加,同时走过的点的权值不可以重复计算,问你k次之后最大得到多大的值。

    做法:我们倒着存边,两次dfs第一次求每个点到根节点的权值,然后将这个权值从大到小排序,第二次dfs贪心遍历每个从大到小排好序的节点,最后将得到的遍历结果再从大到小排序,取前k个数求和。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+10;
    #define LL long long
    struct note
    {
        LL id,val;
    } ye[maxn];
    LL val[maxn];
    LL sum[maxn],cnt;
    LL s[maxn];
    vector<int> v[maxn];
    
    LL dfs(int t)
    {
        if(sum[t]>0) return sum[t];
        sum[t]=val[t];
        for(int i=0; i<v[t].size(); i++)
            sum[t]+=dfs(v[t][i]);
        return sum[t];
    }
    
    LL dfs1(int u)
    {
        if(sum[u]>0)return 0;
        sum[u]=val[u];
        for(int i=0; i<v[u].size(); i++)
        {
            int x=v[u][i];
            sum[u]+=dfs1(x);
        }
        return sum[u];
    }
    bool cmp(note a,note b)
    {
        return a.val>b.val;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        for(int it=1; it<=t; it++)
        {
    
            int n,m;
            scanf("%d%d",&n,&m);
            for(int i=1; i<=n; i++)
                v[i].clear();
            memset(sum,0,sizeof(sum));
            memset(s,0,sizeof(s));
            cnt=0;
            for(int i=1; i<=n; i++)
                scanf("%lld",&val[i]);
            for(int i=1; i<=n-1; i++)
            {
                int a,b;
                scanf("%d%d",&a,&b);
                v[b].push_back(a);
            }
            cnt=0; 
            for(int i=1; i<=n; i++)
            {
                ye[++cnt].id=i;
                ye[cnt].val=dfs(i);
            }
            for(int i=1; i<=n; i++)
            {
                ye[i].id=i;
                ye[i].val=dfs(i);
            }
            sort(ye+1,ye+1+n,cmp);
    
            memset(sum,0,sizeof(sum));
            for(int i=1; i<=n; i++)
                s[i]=dfs1(ye[i].id);
            LL ans=0;
            sort(s+1,s+1+n);
            for(int i=1; i<=m; i++)
                ans+=s[n-i+1];
            printf("Case #%d: %lld
    ",it,ans);
        }
    }
  • 相关阅读:
    软件测试初探
    weiPHPOneThink1.0开发手册
    关于.aspx与.aspx.cs的关系
    佩服的牛人
    当客户说“没钱”,我该怎么应对?
    weiphp 简介笔记
    FlashFXP、LeapFTP、CuteFTP 等FTP软件二进制上传或下载方法
    集体智慧编程(一)
    Sargur Srihari 的两个课程 ML和DM
    一个神人Hoifung Poon
  • 原文地址:https://www.cnblogs.com/dongdong25800/p/10827353.html
Copyright © 2020-2023  润新知