HDU5293 Tree chain problem - 树形dp&树状数组优化
来源:互联网 发布:显卡软件超频 编辑:程序博客网 时间:2024/06/04 18:05
题目描述
题目大意:
给定一棵有 n 个点的树,以及 m 条树链,其中第 i 条树链 的价值为 wi,请选择一些没有公共点的树链,使得价值和最大。
1 ≤n,m≤ 100000。
Source:2015 Multi-University Training Contest 1
分析:
- 设f[u]为u为根的子树上选择没有公共点的树链所得的最大价值和。
- 转移方程:
枚举链的两端点的lca为u的链,记w为当前链的价值f[u]=max{∑f[u.son],w+∑k为当前链上的节点的儿子f[k]} 时间复杂度O((n+m)*n),过不了,选择优化,记sum[u]为u的所有儿子v的f[v]之和,得到:
f[u]=max{∑f[u.son],w+∑j为当前链上的节点sum[j]−f[j]}
(链上的点会在它的父亲的sum[]中多加,要再减去)可根据dfs序维护树状数组来实现优化。
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;#define MAXN 100000#define MAXM 100000#define MAXLOG 20typedef long long LL;struct node{ int v; node *next;}edge[MAXN*2+10],*adj[MAXN+10],*ecnt=&edge[0];vector<int> pnt[MAXN+10];int n,m,LogN,chain[MAXM+10][3];int fa[MAXN+10],dep[MAXN+10],P[MAXN+10][MAXLOG+10];int in[MAXN+10],out[MAXN+10],cntd;LL c[2*MAXN+10],f[MAXN+10];void Init(){ memset(adj,0,sizeof adj); ecnt=&edge[0]; memset(pnt,0,sizeof pnt); memset(fa,0,sizeof fa); memset(dep,0,sizeof dep); memset(f,0,sizeof f); cntd=0; memset(c,0,sizeof c);}void addedge(int u,int v){ node *p=++ecnt; p->v=v; p->next=adj[u]; adj[u]=p;}void dfs(int u,int prev,int L){ fa[u]=prev; dep[u]=L; for(node *p=adj[u];p;p=p->next){ if(p->v==fa[u]) continue; dfs(p->v,u,L+1); }}void LCA_pre(){ memset(P,-1,sizeof P); for(int i=1;i<=n;i++) P[i][0]=fa[i]; for(LogN=0;(1<<LogN)<=n;LogN++); LogN--; for(int j=1;j<=LogN;j++){ for(int i=1;i<=n;i++) if(P[i][j-1]!=-1) P[i][j]=P[P[i][j-1]][j-1]; }}int LCA(int x,int y){ if(dep[x]<dep[y]) swap(x,y); int Logx; for(Logx=0;(1<<Logx)<=dep[x];Logx++); Logx--; for(int i=Logx;i>=0;i--) if(dep[P[x][i]]>=dep[y]) x=P[x][i]; if(x==y) return x; for(int i=Logx;i>=0;i--) if(P[x][i]!=P[y][i]) x=P[x][i],y=P[y][i]; return fa[x];}void read(){ int x,y; scanf("%d%d",&n,&m); for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); addedge(x,y); addedge(y,x); } dfs(1,0,1); LCA_pre(); for(int i=1;i<=m;i++){ scanf("%d%d%d",&chain[i][0],&chain[i][1],&chain[i][2]); int lca=LCA(chain[i][0],chain[i][1]); pnt[lca].push_back(i); }}int lowbit(int x){ return x&(-x);}void Update(int x,LL d){ while(x<=2*n){ c[x]+=d; x+=lowbit(x); }}LL Getsum(int x){ LL ret=0; while(x){ ret+=c[x]; x-=lowbit(x); } return ret;}void DP(int u) //dfs for dp on the tree{ LL g_u=0; in[u]=++cntd; for(node *p=adj[u];p;p=p->next){ if(p->v==fa[u]) continue; DP(p->v); g_u+=f[p->v]; } out[u]=++cntd; Update(in[u],g_u); Update(out[u]+1,-g_u); f[u]=g_u; int side=pnt[u].size(); for(int i=0,num;i<side;i++){ num=pnt[u][i]; f[u]=max(f[u],Getsum(out[chain[num][0]])+Getsum(out[chain[num][1]])+1LL*chain[num][2]-g_u); } Update(in[u],-f[u]); Update(out[u]+1,f[u]);}int main(){ int T; scanf("%d",&T); while(T--){ Init(); read(); DP(1); printf("%I64d\n",f[1]); }}
1 0
- HDU5293 Tree chain problem - 树形dp&树状数组优化
- 树形DP - hdu5293 Tree chain problem
- hdu5293 Tree chain problem 树形dp+线段树
- HDU5293:Tree chain problem(树形dp & LCA)
- hdu5293(2015多校1)--Tree chain problem(树状dp)
- HDU5293 Tree chain problem
- 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序+树状数组
- HDU 5293 Tree chain problem【树形DP】
- hdu 5293 Tree chain problem【树状dp+dfs序+树状数组】
- HDU 5293 TREE CHAIN PROBLEM LCT+树形DP
- HDOJ 5293 Tree chain problem LCA+树链剖分+树形DP
- 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 dfs序+树形dp
- poj3237 树链部分 边权模板
- Linux用户组、用户基础概念及常用命令(CentOS)
- h264数据通过RTP分片传输的例子
- 响应头与请求头
- Oracle12c中数据删除(delete)新特性之数据库内归档功能
- HDU5293 Tree chain problem - 树形dp&树状数组优化
- 我的博客 http://www.wlheihei.com
- IOS开发中的CGFloat、CGPoint、CGSize和CGRect
- 星型数据仓库olap工具kylin介绍
- Oracle 11g导出的dmp文件导入到10g
- POJ 3352|Road Construction|边双联通分量|Tarjan
- 利用c语言绘制漫天星空-动画
- 2015年阿里巴巴中间件比赛rpc框架
- SVN图标不显示的2种处理方式