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
- hdu 5293 Tree chain problem(树链剖分+树形dp)
- HDU 5293 Tree chain problem(树形DP+树链剖分+LCA)
- HDU 5293 Tree chain problem(树形DP+树链剖分)
- HDU 5293 Tree chain problem【树形DP】
- HDU 5293 Tree chain problem [树链剖分+线段树+树形DP]
- HDU 5293 TREE CHAIN PROBLEM LCT+树形DP
- HDU 5293 Tree chain problem dfs序+树形dp
- HDU 5293 Tree chain problem 树形DP+LCA+树链剖分+线段树
- HDOJ 5293 Tree chain problem LCA+树链剖分+树形DP
- 【HDU】5293 Tree chain problem【DP+LCA】
- 多校第一场 1006 hdu 5293 Tree chain problem(离线LCA+时间戳+树形dp)
- hdu 5293 Tree chain problem(15多校第一场1006)(树形dp+树状数组+LCA)
- HDU 5293 Tree chain problem(数链问题)【LCA+树形dp+dfs序+树状数组】
- HDU 5293 Tree chain problem 树形DP+LCA+DFS序+树状数组
- HDU5293:Tree chain problem(树形dp & LCA)
- 树形DP - hdu5293 Tree chain problem
- HDU 5293(Tree chain problem-树链剖分)
- hdu5293 Tree chain problem 树形dp+线段树
- 微信支付接入指南
- 图算法6之1008
- Java Web学习总结(20)——基于ZooKeeper的分布式session实现
- 一篇文章,掌握所有开源数据库的现状
- 通过ServiceManager统一管理aidl服务
- HDU 5293 Tree chain problem(树形DP+树链剖分)
- POJ2533/hdoj1950【DP】
- SearchView去掉下划线
- Android短信验证
- void QObject::moveToThread(QThread * targetThread)
- 安装myeclipse之前jdk的安装及配置(附:jre)
- 数组指针与指针数组
- JVM运行时数据区域
- 最小二乘法