树上最小权覆盖(可并堆)

题目大意

  以\(1\)为根,\(n\)个点的树,给\(m\)条直上直下的链,每个链有权值,求最小权覆盖。

解题思路

  曾经猫老师讲过的一道题。首先考虑序列上的最小权区间覆盖,一个人尽皆知的方法是数据结构优化\(dp\)做,但还有一种方法是用堆。堆里存二元组\((a,b)\)表示花费\(a\)使得\([1,b]\)被覆盖,这个以\(a\)为关键字,然后按照左端点排序,每次取出\(b\)\([l,r]\)内的最小值,然后更新答案。尝试把这个做法扩展到树上,发现需要进行合并,那么就可以可并堆了,时间复杂度\(O(nlogn)\)

代码

#pragma GCC optimize("inline","Ofast")
#pragma GCC optimize(3)
#include<bits/stdc++.h>

using namespace std;
const int N=1000005;

inline int rd(){
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    return f?x:-x;
}

int n,m,fa[N],dep[N],rt[N],dis[N],ch[N][2],top[N],val[N],tot,tag[N];
vector<pair<int,int> > v[N];
vector<int> G[N];

void pushdown(int x){
    if(tag[x]){
        val[x]+=tag[x];
        tag[ch[x][0]]+=tag[x];
        tag[ch[x][1]]+=tag[x];
        tag[x]=0;
    }
}

int merge(int x,int y){
    if(!x || !y) return (x|y);
    pushdown(x); pushdown(y);
    if(val[x]>val[y]) swap(x,y);
    ch[x][1]=merge(ch[x][1],y);
    if(dis[ch[x][0]]<dis[ch[x][1]]) swap(ch[x][0],ch[x][1]);
    dis[x]=dis[ch[x][1]]+1; 
    return x;
}

void DFS(int x){
    for(int i=0;i<v[x].size();i++){
        val[++tot]=(v[x][i]).first;
        top[tot]=(v[x][i]).second;
        rt[x]=merge(rt[x],tot);
    }
    int sum=0,w;
    for(int i=0;i<G[x].size();i++){
        DFS(G[x][i]); pushdown(rt[G[x][i]]); 
        w=val[rt[G[x][i]]]; tag[rt[x]]+=w; 
        tag[rt[G[x][i]]]+=sum; sum+=w;
        rt[x]=merge(rt[x],rt[G[x][i]]);
    }
    while(rt[x]){
        pushdown(rt[x]);
        if(dep[top[rt[x]]]>dep[x]) rt[x]=merge(ch[rt[x]][0],ch[rt[x]][1]);
        else break;
    }
    if(!rt[x]) {puts("-1"); exit(0);}
}

int main(){
    dep[1]=1;
    n=rd(),m=rd(); int x,y,z;
    for(int i=2;i<=n;i++){
        fa[i]=rd(); dep[i]=dep[fa[i]]+1;
        G[fa[i]].push_back(i);
    }
    for(int i=1;i<=m;i++){
        x=rd(),y=rd(),z=rd();
        v[y].push_back(make_pair(z,x));
    }
    DFS(1); printf("%d\n",val[rt[1]]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/sdfzsyq/p/10561176.html