zoukankan      html  css  js  c++  java
  • HDU5293 : Tree chain problem

    问题即:选择价值和最多的链,使得每个点最多被一条链覆盖。

    那么考虑其对偶问题:选择最少的点(每个点可以重复选),使得每条链上选了至少$w_i$个点。

    那么将链按照LCA的深度从大到小排序,每次若发现点数不够,则在LCA处补充点,树链剖分+线段树维护。

    时间复杂度$O(mlog^2n)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=100010,M=262150;
    int Case,cas,n,m,q,i,op,x,y,z;
    int g[N],v[N<<1],nxt[N<<1],ed;
    int size[N],son[N],f[N],d[N],st[N],top[N],dfn;
    int val[M];
    int ans;
    struct E{int x,y,z,w;}e[N];
    inline bool cmp(const E&a,const E&b){return d[a.z]<d[b.z];}
    inline void addedge(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
    void dfs(int x){
        size[x]=1;
        for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
            f[v[i]]=x,d[v[i]]=d[x]+1;
            dfs(v[i]),size[x]+=size[v[i]];
            if(size[v[i]]>size[son[x]])son[x]=v[i];
        }
    }
    void dfs2(int x,int y){
        st[x]=++dfn;top[x]=y;
        if(son[x])dfs2(son[x],y);
        for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]);
    }
    void build(int x,int a,int b){
        val[x]=0;
        if(a==b)return;
        int mid=(a+b)>>1;
        build(x<<1,a,mid),build(x<<1|1,mid+1,b);
    }
    void change(int x,int a,int b,int c,int p){
        val[x]+=p;
        if(a==b)return;
        int mid=(a+b)>>1;
        if(c<=mid)change(x<<1,a,mid,c,p);
        else change(x<<1|1,mid+1,b,c,p);
    }
    int ask(int x,int a,int b,int c,int d){
        if(c<=a&&b<=d)return val[x];
        int mid=(a+b)>>1,t=0;
        if(c<=mid)t=ask(x<<1,a,mid,c,d);
        if(d>mid)t+=ask(x<<1|1,mid+1,b,c,d);
        return t;
    }
    inline int lca(int x,int y){
        for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]])swap(x,y);
        return d[x]<d[y]?x:y;
    }
    inline int chain(int x,int y){
        int t=0;
        for(;top[x]!=top[y];x=f[top[x]]){
            if(d[top[x]]<d[top[y]])swap(x,y);
            t+=ask(1,1,n,st[top[x]],st[x]);
        }
        if(d[x]<d[y])swap(x,y);
        t+=ask(1,1,n,st[y],st[x]);
        return t;
    }
    inline void gao(int x,int y,int z,int w){
        int t=chain(x,y);
        if(t>=w)return;
        w-=t;
        ans+=w;
        change(1,1,n,st[z],w);
    }
    int main(){
        scanf("%d",&Case);
        while(Case--){
            scanf("%d%d",&n,&m);
            for(i=1;i<n;i++){
                scanf("%d%d",&x,&y);
                addedge(x,y),addedge(y,x);
            }
            dfs(1);
            dfs2(1,1);
            build(1,1,n);
            for(i=1;i<=m;i++){
                scanf("%d%d%d",&x,&y,&e[i].w);
                e[i].x=x,e[i].y=y;
                e[i].z=lca(x,y);
            }
            sort(e+1,e+m+1,cmp);
            for(i=m;i;i--)gao(e[i].x,e[i].y,e[i].z,e[i].w);
            printf("%d
    ",ans);
            for(i=0;i<=n;i++)g[i]=size[i]=son[i]=f[i]=d[i]=st[i]=top[i]=0;
            ed=dfn=ans=0;
        }
    }
    

      

  • 相关阅读:
    DataTable.AcceptChanges方法有何用处
    中山西路620号 的人才服务中心搬到 梅园路77号去了
    Congos
    ps -aux返回超过100%
    to_date如何处理毫秒?
    SNMP_802.1
    交换机
    Oracle字符编码
    CRON
    交换机
  • 原文地址:https://www.cnblogs.com/clrs97/p/7697217.html
Copyright © 2011-2022 走看看