首页 > 其他分享 >BZOJ 3252 攻略(长链剖分模板 链的常用性质 贪心)

BZOJ 3252 攻略(长链剖分模板 链的常用性质 贪心)

时间:2022-12-22 22:24:03浏览次数:69  
标签:hson 长链 ch 剖分 val int 3252 init mx

BZOJ 3252 攻略

​ 给定一棵带边权的树,选择 k 个叶子结点,使这些叶子结点与根节点相连,形成 k 条路径。输出被路径覆盖的所有边的边权和的最大值(同一条边若被重复覆盖只算一次)。

思路:

​ 很容易看出,是选择 k 条链。我们可以贪心的想一想,一定是权值和最大的链先被选中,然后选删去这条链后权值最大的链。那就是一个模拟删链的过程,这就是树链剖分的经典应用。我们进行长链剖分,但是这里的长链不是对深度剖分,是对权值剖分。将每条链塞进优先队列里,取前 k 个即可。

代码:

#include <bits/stdc++.h>

using namespace std;
#define ll long long 
void read(int &x) {int s = 0, f = 1; char ch = getchar(); while(!isdigit(ch)) {f = (ch == '-' ? -1 : f); ch = getchar();} while(isdigit(ch)) {s = s * 10 + ch - '0'; ch = getchar();} x = s * f;}
const int N = 1000005;

int n, k;
vector<int> g[N];
ll val[N];
priority_queue<ll> Q;

int father[N], hson[N];
ll mx_val[N];
void dfs1_init(int u, int fa)
{
    father[u] = fa;
    hson[u] = -1;
    for(int v : g[u])
    {
        if(v == fa) continue;
        dfs1_init(v, u);
        if(hson[u] == -1 || mx_val[v] > mx_val[hson[u]])
            hson[u] = v;
    }
    mx_val[u] = val[u] + mx_val[hson[u]];
}
void dfs2_init(int u, int head)
{
    if(u == head)
        Q.push(mx_val[u]);
    if(hson[u] != -1)
    {
        dfs2_init(hson[u], head);
        for(int v : g[u])
        {
            if(v == father[u] || v == hson[u])
                continue;
            dfs2_init(v, v);
        }
    }
}

void init() 
{
    for(int i = 1; i <= n; i ++)
        g[i].clear();
}

void solve()
{
    read(n); read(k);
    init();
    for(int i = 1; i <= n; i ++)
        scanf("%lld", &val[i]);
    for(int i = 1; i < n; i ++)
    {
        int x, y;
        read(x); read(y);
        g[x].push_back(y);
        g[y].push_back(x);
    }

    dfs1_init(1, 0);
    dfs2_init(1, 1);

    ll res = 0;
    while(Q.size() && k)
        res += Q.top(), Q.pop(), k --;
    printf("%lld\n", res);
}

int main()
{
    int _ = 1;
    while(_--)
        solve();
}

标签:hson,长链,ch,剖分,val,int,3252,init,mx
From: https://www.cnblogs.com/DM11/p/16999709.html

相关文章

  • 最大面积最小的三角剖分 Minimax Triangulation
    #include<iostream>#include<algorithm>#include<cmath>#include<vector>usingnamespacestd;#definemistake(P)(fabs(P)<eps?0:(P<0?-1:1))......
  • 边权树链剖分
    边权树链剖分一般的树链剖分都是维护的点权,而如果要维护边权怎么办呢?思路我们可以把边权转换为点权。一个点有很多个儿子,但只有一个父亲。如果一个节点的点权记录到其儿......
  • 重链剖分学习笔记
    最近在机房自习复习了一下这些东西,主要给自己看的。参考文献:OIWiki《算法竞赛》(罗勇军,郭卫斌著)1重链剖分简介1.1重链剖分基本性质树链剖分,就是把树分成若......
  • 重链剖分学习笔记
    最近在机房自习复习了一下这些东西,主要给自己看的。参考文献:OIWiki《算法竞赛》(罗勇军,郭卫斌著)1重链剖分简介1.1重链剖分基本性质树链剖分,就是把树分成若......
  • 树链剖分学习笔记
    树链剖分学习笔记简介树链剖分是一种可以把树丢到线段树上维护的一种算法,时间复杂度为\(O(n\log^2n)\)。思路一、一些概念1.重儿子:如果一个点有儿子,那么所有儿子中......
  • P3128 [USACO15DEC]Max Flow P(树上倍增和树链剖分)
    思路1(树上倍增$+$树上差分)每次都修改一条从\(u\)到\(v\),不就是树上差分的专门操作吗??直接用倍增求\(LCA\),每次\(d[u]++,d[v]++,d[LCA(u,v)]--,d[f[LCA(u,v)][0]]--\)。......
  • 浅谈树链剖分
    树链剖分定理重儿子:一个节点所有儿子中,子树大小最大的儿子即为重儿子,如有多个,任取一个即可。轻儿子:除了重儿子外的所有儿子。重边:父节点\(\to\)重儿子的边。重链:由......
  • 树链剖分
    树链剖分0x00绪言在阅读这篇文章前,确保你已学会你下内容:线段树深度优先遍历会了这些就可以开始阅读本篇文章了。0x01什么是树剖把一棵树拆成若干个不相交的链,然......
  • POJ3252 Round Numbers
    终于一遍就写对了.第一次没有注意读题导致了一个没有注意到什时候要开始统计.Code#include<iostream>#include<string>#defineintlonglongusingnamespacestd;......
  • 浅析树链剖分
    可以看出树链剖分的作用就是将一棵树变成一个可处理的dfs序,树上操作一般由​​线段树​​来维护,看一下模板题​​BZOJ1036​​和​​POJ3237​​。......