• bzoj3252 攻略



    题目简述:树版[k取方格数]
    众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏。
    今天他得到了一款新游戏《XX半岛》,这款游戏有n个场景(scene),某些场景可以通过不同的选择支到达其他场景。所有场景和选择支构成树状结构:开始游戏时在根节点(共通线),叶子节点为结局。每个场景有一个价值,现在桂马开启攻略之神模式,同时攻略k次该游戏,问他观赏到的场景的价值和最大是多少(同一场景观看多次是不能重复得到价值的)
    “为什么你还没玩就知道每个场景的价值呢?”
    “我已经看到结局了。”
    Input
    第一行两个正整数n,k
    第二行n个正整数,表示每个场景的价值
    以下n-1行,每行2个整数a,b,表示a场景有个选择支通向b场景(即a是b的父亲)
    保证场景1为根节点 对于100%的数据,n<=200000,1<=场景价值<=2^31-1
    Output
    输出一个整数表示答案
    Sample Input
    5 2
    4 3 2 1 1
    1 2
    1 5
    2 3
    2 4

    Sol:找出每个点的最长链放入堆中(注意权值是在点上面的),每次找出最长链,并从堆中删除

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int N = 200005;
    struct edges 
    {
        int next, to;
        edges() {}
        edges(int _n, int _t) : next(_n), to(_t) {}
    } e[N];
    struct data 
    {
        ll first;
        int w;
        data() {}
        data(ll _f, int _w) : first(_f), w(_w) {}
         
        inline bool operator < (const data &b) const 
    	{
            return first < b.first;
        }
    };
     
    int n, k;
    int first[N], tot;
    int v[N];
    bool vis[N];
    ll mx[N], ans;
    priority_queue <data> h;
    inline int read() 
    {
        int x = 0, sgn = 1;
        char ch = getchar();
        while (ch < '0' || '9' < ch) 
    	{
            if (ch == '-') sgn = -1;
            ch = getchar();
        }
        while ('0' <= ch && ch <= '9') 
    	{
            x = x * 10 + ch - '0';
            ch = getchar();
        }
        return sgn * x;
    }
     
    inline void add_edge(int x, int y) 
    {
        e[++tot] = edges(first[x], y);
        first[x] = tot;
    }
     
    void dfs(int p) 
    {
        int x, y;
        for (x = first[p]; x; x = e[x].next)
            dfs(y = e[x].to), mx[p] = max(mx[p], mx[y]);
        mx[p] += v[p];
        h.push(data(mx[p], p));
        //找出每个点的最长链,放到堆中 
    }
     
    void del(int p) 
    {
        int x, y;
        vis[p] = 1;//将其打上删除标记,在堆中并没有删除之
        for (x = first[p]; x; x = e[x].next) 
            if (mx[y = e[x].to] == mx[p] - v[p]) 
    		{
                del(y);
                break;
            }
    }
     
    int main() 
    {
        int i, p, x, y;
        n = read(), k = read();
        for (i = 1; i <= n; ++i) v[i] = read();
        for (i = 1; i < n; ++i) 
    	{
            x = read(), y = read();
            add_edge(x, y);
        }
        dfs(1);
        for (; k && !h.empty(); --k) 
    	{
            while (vis[h.top().w] && !h.empty()) 
            //如果这个点删除过了,并且堆并不为空时 
    		    h.pop();
            if (h.empty())
    		    break;
            ans += mx[p = h.top().w];
            del(p);
        }
        printf("%lld\n", ans);
        return 0;
    }
    

      

  • 相关阅读:
    【Python】pip导出当前项目所用的包list列表
    什么叫他妈的惊喜
    自我介绍
    IDEA创建SpringBoot时无法连接https://start.spring.io
    漫话docker的衰落与kubernetes的兴起
    基于Kubernetes和OpenKruise的可变基础设施实践
    浅析
    浅析
    浅析
    浅析
  • 原文地址:https://www.cnblogs.com/cutemush/p/11679210.html
Copyright © 2020-2023  润新知