HDU 5293 Tree chain problem(树形DP+树链剖分)

来源:互联网 发布:毕业论文数据库 编辑:程序博客网 时间:2024/06/15 23:16

题意:一颗n节点树上有m条链,每条链有权重,求一个链的集合使权重和最大且两两不相交。

解析:令dp[i]为以i为根的子树的最大权重和。

如果i不在链上,则有dp[i] = sigma(dp[k]) k为i的子节点

如果i在某一条链(u,v,w)上,那么dp[i] = w + sigma(dp[k]) k为链上所有节点的子节点。对于该值,我们可以统计统计链上节点的所有子节点dp的和 - 链上节点dp和(经树链剖分后用树状数组维护)。


[code]:

#pragma comment(linker, "/STACK:1024000000,1024000000")#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<vector>#define lson l , mid , rt<<1#define rson mid+1, r, rt<<1|1#define lowbit(i) (i&-i)using namespace std;const int maxn = 1e5+5;inline bool read(int &ret){    char c;int sgn;    if(c = getchar(),c==EOF) return 0;    while(c != '-'&&(c<'0'||c>'9')) c=getchar();    sgn = (c=='-')?-1:1;    ret = (c=='-')?0:(c-'0');    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');    ret*=sgn;    return 1;}struct Chain{    int u,v,w;    Chain(int u,int v,int w):u(u),v(v),w(w){}};struct Nod{    int b,next;    void init(int b,int next){        this->b=b;this->next=next;    }}buf[2*maxn];int n,m,len,E[maxn];vector<Chain> G[maxn];struct LCA{    int rmq[maxn<<1],pos[maxn<<3];    int F[maxn<<1],P[maxn],lca;    void dfs(int u,int pre,int deep){        int i,v;        lca++;F[lca]=u;P[u]=lca;rmq[lca]=deep;        for(i=E[u];i!=-1;i=buf[i].next){            v = buf[i].b;            if(v == pre) continue;            dfs(v,u,deep+1);            lca++;F[lca]=u;rmq[lca]=deep;        }    }    void build(int l,int r,int rt){        if(l == r) { pos[rt] = l; return; }        int mid = (l + r) >> 1;        build(lson);build(rson);        pos[rt] = rmq[pos[rt<<1]] < rmq[pos[rt<<1|1]]? pos[rt<<1]:pos[rt<<1|1];    }    int query(int a,int b,int l,int r,int rt){        if(l > b || r < a) return 0;        if(a <= l && r <= b) return pos[rt];        int o1,o2,mid = (l + r) >>1;        o1 = query(a,b,lson);o2 = query(a,b,rson);        return rmq[o1] < rmq[o2] ? o1 : o2;    }    void make(int root){        lca = 0;        memset(rmq,63,sizeof(rmq));        dfs(root,-1,0);        build(1,lca,1);    }    int ancestor(int a,int b){        int ca = P[a],cb = P[b];        if(ca > cb) swap(ca,cb);        return F[query(ca,cb,1,lca,1)];    }}ac;int dp[maxn];int num[maxn],dep[maxn],par[maxn],son[maxn],head[maxn],P[maxn],cnt;struct BIT{    int bit[2][maxn],range;    void init(int range){        this->range = range;        for(int i = 1;i <= range;i++) bit[0][i] = bit[1][i] = 0;    }    void add(int k,int x,int id){        for(;k<=range;k+=lowbit(k)) bit[id][k]+=x;    }    int sum(int k,int id){        int res = 0;        for(;k;k-=lowbit(k)) res += bit[id][k];        return res;    }    int query(int l,int r,int id){        return sum(r,id)-sum(l-1,id);    }}bt;void init(){    len = cnt = 0;    memset(E,-1,n*sizeof(int));    for(int i = 0;i < n;i++) G[i].clear();}void add_edge(int a,int b){    buf[len].init(b,E[a]);E[a]=len++;    buf[len].init(a,E[b]);E[b]=len++;}void dfs(int u,int pre){    int i,v;    num[u] = 1;son[u] = -1;par[u] = pre;dep[u] = pre!=-1?dep[pre]+1:0;    for(i=E[u];i!=-1;i=buf[i].next){        v = buf[i].b;        if(v == pre) continue;        dfs(v,u);        if(son[u]==-1||num[v]>num[son[u]]) son[u] = v;        num[u]+=num[v];    }}void buildQTree(int u,int hd){    int i,v;    cnt++;    head[u] = hd;P[u]=cnt;    if(son[u]!=-1) buildQTree(son[u],hd);    for(i=E[u];i!=-1;i=buf[i].next){        v = buf[i].b;        if(v == son[u] || v == par[u]) continue;        buildQTree(v,v);    }}int query(int a,int b,int id){    int ha = head[a],hb = head[b], res = 0;    while(ha != hb){        if(ha == -1 || (ha != -1 && hb != -1 && dep[ha] < dep[hb])){            swap(ha,hb);swap(a,b);        }        res += bt.query(P[ha],P[a],id);        a = par[ha];ha = a != -1 ?head[a] :-1;    }    if(a == b) return res + bt.query(P[a],P[a],id);    if(dep[a] > dep[b]) swap(a,b);    return res + bt.query(P[a],P[b],id);}void DP(int u,int pre){    int i,v,v1,v2,w,sum = 0;    dp[u] = 0;    for(i = E[u];i != -1;i = buf[i].next){        v = buf[i].b;        if(v == pre) continue;        DP(v,u);        dp[u] += dp[v];        //bt.add(P[u],dp[v],1);    }    bt.add(P[u],dp[u],1);    sum = dp[u];//printf("current node %d\n",u);    for(i = 0;i < G[u].size();i++){        v1 = G[u][i].u;v2 = G[u][i].v;w = G[u][i].w;//        dp[u] = max(dp[u],w-sum+query(v1,u,1)-query(v1,u,0)  //                  +query(v2,u,1)-query(v2,u,0));//printf("%d %d %d %d\n",query(v1,u,1),query(v1,u,0)    //                ,query(v2,u,1),query(v2,u,0));        dp[u] = max(dp[u],w+query(v1,v2,1)-query(v1,v2,0));//printf("temp : %d %d %d\n",query(v1,v2,1),query(v1,v2,0),w+query(v1,v2,1)-query(v1,v2,0));//printf("-> %d %d %d %d\n",v1,v2,w,dp[u]);    }//printf("answer %d\n",dp[u]);    bt.add(P[u],dp[u],0);}int main(){    int i,j,cas,u,v,w,op;    read(cas);    while(cas--){        read(n);read(m);        init();        for(i = 1;i < n;i++){            read(u);read(v);u--,v--;            add_edge(u,v);        }        ac.make(0);        for(i = 0;i < m;i++){            read(u);read(v);read(w);u--,v--;            G[ac.ancestor(u,v)].push_back(Chain(u,v,w));        }        dfs(0,-1);        buildQTree(0,0);        bt.init(cnt);        DP(0,-1);        printf("%d\n",dp[0]);    }    return 0;}



0 0
原创粉丝点击