hdu5293 Tree chain problem 树形dp+线段树
2017-04-16 08:21
375 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5293
在一棵树中,给出若干条链和链的权值。求选取不相交的链使得权值和最大。
比赛的时候以为是树链剖分就果断没去想,事实上是没思路。
看了题解,原来是树形dp。话说多校第一场树形dp还真多。
。
。。
维护d[i],表示以i为根节点的子树的最优答案。
sum[i]表示i的儿子节点(仅仅能是儿子节点)的d值和。
那么答案就是d[root]。
怎样更新d值
d[i] = max(sum[i] , w[p]+sigma sum[j] -
sigma d[j] ); p为以i为lca的链 。j为链上的点(注意:不须要减去d[i])
也就是。对于i,
要么是不选i,答案即sum[i]。他的儿子和。
要么是选i,即找一条过i的链,链的权值 + 这棵子树上不在链上的距离链近期的点的d值和。
维护链上的的sum和,d和 用线段树。
先通过树的遍历序将树上的节点链话。然后区间改动,单点查询。(每一个点的信息是改点到根节点路径上的和)
代码:
在一棵树中,给出若干条链和链的权值。求选取不相交的链使得权值和最大。
比赛的时候以为是树链剖分就果断没去想,事实上是没思路。
看了题解,原来是树形dp。话说多校第一场树形dp还真多。
。
。。
维护d[i],表示以i为根节点的子树的最优答案。
sum[i]表示i的儿子节点(仅仅能是儿子节点)的d值和。
那么答案就是d[root]。
怎样更新d值
d[i] = max(sum[i] , w[p]+sigma sum[j] -
sigma d[j] ); p为以i为lca的链 。j为链上的点(注意:不须要减去d[i])
也就是。对于i,
要么是不选i,答案即sum[i]。他的儿子和。
要么是选i,即找一条过i的链,链的权值 + 这棵子树上不在链上的距离链近期的点的d值和。
维护链上的的sum和,d和 用线段树。
先通过树的遍历序将树上的节点链话。然后区间改动,单点查询。(每一个点的信息是改点到根节点路径上的和)
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> #include<cmath> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int N = 100000+10; typedef long long ll; const int maxh = 25; int st ,ed ,clock; // ************************************ #define Lson Ls,L,mid #define Rson Rs,mid+1,R const int maxn = 100000+10; const int inf = 100000000; struct Node{ ll val, set; ll val2 , set2; }tree[N<<2]; inline void update(Node& fa, Node& Ls, Node& Rs){ fa.val = Ls.val + Rs.val; fa.val2 = Ls.val2 + Rs.val2; } inline void pushdown(Node& fa, Node& Ls, Node& Rs){ if (fa.set != 0){ Ls.val += fa.set; Ls.set += fa.set; Rs.val += fa.set; Rs.set += fa.set; fa.set = 0; } if (fa.set2 != 0){ Ls.val2 += fa.set2; Ls.set2 += fa.set2; Rs.val2 += fa.set2; Rs.set2 += fa.set2; fa.set2 = 0; } } void insert(int v, int L, int R, int p, int q, ll delta,ll delta2){ if(p<=st[2]&& q>=st[2]&& delta2) { } if (p<=L && R<=q){ tree[v].val += delta; tree[v].set += delta; tree[v].val2 += delta2; tree[v].set2 += delta2; return; } int Ls = v<<1, Rs = Ls+1, mid = (L+R)/2; pushdown(tree[v], tree[Ls], tree[Rs]); if (q<=mid) insert(Lson, p, q, delta,delta2); else if (p>mid) insert(Rson, p, q, delta,delta2); else{ insert(Lson, p, q, delta,delta2); insert(Rson, p, q, delta,delta2); } // update(tree[v], tree[Ls], tree[Rs]); } ll query(int v, int L, int R,int ql, int qr){ if(ql<=L && R<=qr){ return tree[v].val; } int Ls = v<<1, Rs = Ls+1, mid = (L+R)/2; pushdown(tree[v], tree[Ls], tree[Rs]); ll ans = 0; if(qr<=mid) ans = query(Lson,ql,qr); else if(ql>mid) ans = query(Rson,ql,qr); else{ ans = query(Lson,ql,qr) + query(Rson,ql,qr); } // update(tree[v], tree[Ls], tree[Rs]); return ans ; } ll query2(int v, int L, int R,int ql, int qr){ if(ql<=L && R<=qr){ return tree[v].val2; } int Ls = v<<1, Rs = Ls+1, mid = (L+R)/2; pushdown(tree[v], tree[Ls], tree[Rs]); ll ans = 0; if(qr<=mid) ans = query2(Lson,ql,qr); else if(ql>mid) ans = query2(Rson,ql,qr); else{ ans = query2(Lson,ql,qr) + query2(Rson,ql,qr); } // update(tree[v], tree[Ls], tree[Rs]); return ans ; } // *************************************** ll d ,sum ; vector<int> g ; vector<int> list ; struct pp{ int u,v,w; }p ; int n,m,dep ; int anc [maxh+1]; void dfs(int x,int pre){ st[x] = ++clock; anc[x][0] = pre; for(int i=0;i<g[x].size();i++)if(g[x][i]!=pre){ int u = g[x][i]; dep[u] = dep[x] + 1; dfs(u,x); } ed[x] = clock; } void lca_init(){ clock = 0; dep[1] = 1; dfs(1,-1); for(int i=1;i<=maxh-1;i++){ for(int j=1;j<=n;j++) if(anc[j][i-1]<0) anc[j][i] = -1; else anc[j][i] = anc[anc[j][i-1]][i-1]; } } int swim(int x,int H){ for(int i=0;H;i++){ if(H&1) x = anc[x][i]; H >>= 1; } return x; } int lca(int u,int v){ if(dep[u]>dep[v]) swap(u,v); int H = dep[v]-dep[u]; v = swim(v,H); if(u==v) return u; for(int k=maxh-1;k>=0;k--) if(anc[u][k]!=anc[v][k]){ u = anc[u][k]; v = anc[v][k]; } return anc[u][0]; } ll find(int u,int v,int la){ ll ans = 0; ll s1 = query2(1,1,n,st[u],st[u]); ll s2 = query2(1,1,n,st[v],st[v]); ans = s1 + s2; ll d1 = query(1,1,n,st[u],st[u]); ll d2 = query(1,1,n,st[v],st[v]); ans -= d1 + d2; return ans+sum[la]; } ll dfs_tree(int x,int pre){ if(d[x]!=-1) return d[x]; ll res = 0; sum[x] = 0; for(int i=0;i<g[x].size();i++)if(g[x][i]!=pre){ int u = g[x][i]; sum[x] += dfs_tree(u,x); } d[x] = sum[x]; for(int i=0;i<list[x].size();i++){ int id = list[x][i]; ll tmp = p[id].w ; ll tmp1 = find(p[id].u,p[id].v,x); tmp += tmp1; d[x] = max(d[x] , tmp); } // update insert(1,1,n,st[x],ed[x],d[x],sum[x]); return d[x]; } void solve(){ memset(d,-1,sizeof(d)); memset(tree,0,sizeof(tree)); lca_init(); for(int i=1;i<=n;i++) list[i].clear(); for(int i=1;i<=m;i++){ int u = p[i].u , v = p[i].v; int la = lca(u,v); list[la].push_back(i); } dfs_tree(1,-1); } int main(){ int T; cin >> T; while(T--){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) g[i].clear(); for(int i=1;i<=n-1;i++){ int u,v; scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); } for(int i=1;i<=m;i++){ int u,v,w; scanf("%d%d%d",&p[i].u,&p[i].v,&p[i].w); } solve(); printf("%I64d\n",d[1]); } return 0; }
相关文章推荐
- hdu5293 Tree chain problem 树形dp+线段树
- 树形DP - hdu5293 Tree chain problem
- HDU5293:Tree chain problem(树形dp & LCA)
- HDU 5293 Tree chain problem 树形DP+LCA+树链剖分+线段树
- HDU5293 : Tree chain problem
- HDU 5293 Tree chain problem(数链问题)【LCA+树形dp+dfs序+树状数组】
- 多校第一场 1006 hdu 5293 Tree chain problem(离线LCA+时间戳+树形dp)
- HDU 5293 Tree chain problem(树形DP+树链剖分)
- [2015hdu多校联赛补题]hdu5293 Tree chain problem
- HDU 5293 Tree chain problem 树形DP
- (中等) HDU 5293 Tree chain problem,树链剖分+树形DP。
- hdu 5293 Tree chain problem(15多校第一场1006)(树形dp+树状数组+LCA)
- 【HDU 5233】Tree chain problem (树形DP+树剖+线段树|树状数组)最大权不相交树链集
- hdu5293(2015多校1)--Tree chain problem(树状dp)
- HDU 5293 Tree chain problem【树形DP】
- HDU 5293 Tree chain problem [树链剖分+线段树+树形DP]
- HDU 5293 Tree chain problem(树形DP+树链剖分+LCA)
- hdu5293(2015多校1)--Tree chain problem(树状dp)
- HDU 5293 Tree chain problem - 树形dp&树状数组优化
- hdu 5293 Tree chain problem(树链剖分+树形dp)