码迷,mamicode.com
首页 > 其他好文 > 详细

[2015hdu多校联赛补题]hdu5293 Tree chain problem

时间:2015-08-03 01:03:59      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5293

题意:给你一棵n个点的树,和一些该树上的树链,每个树链有一定的权值,要求选出一些不相交的树链,使他们的权值和尽量大

解:

树形dp,dp[x]表示以x为根节点的子树的解,那么就可以基于在当前结点对树链的选和不选进行dp

现在有两个问题:

1、在树链上的哪个点进行选择?

2、选和不选分别如何操作?

 

对于第一个问题,粗略想一下(在解决问题二的时候会发现),树链上最浅的一个点(也就是树链两端的lca)上选择是可行的

对于第二个问题,(假设现在在点u)不选的话,dp[u]=Sum(dp[v])(v为u的子节点),用sum[u]记录Sum(dp[v])(v为u的子节点),有dp[u]=sum[u]

选择的话,对于每一个lca在u点的树链c,

dp[u]=max(dp[u],Sum(dp[v1])+c.w(v1为c上所有节点的子节点, c.w为该链的权值))

dp[u]=max(dp[u],Sum(sum[x])-Sum(dp[x])+c.w(x为c上所有节点, c.w为该链的权值))

这个链上所有节点的某值和,用dfs序+树状数组维护一下就好了

技术分享
  1 /*
  2  * Problem:  
  3  * Author:  SHJWUDP
  4  * Created Time:  2015/8/2 星期日 22:07:32
  5  * File Name: 233.cpp
  6  * State: 
  7  * Memo: 
  8  */
  9 #include <iostream>
 10 #include <cstdio>
 11 #include <cstring>
 12 #include <algorithm>
 13 #include <vector>
 14 #pragma comment(linker, "/STACK:1024000000,1024000000") 
 15 
 16 using namespace std;
 17 
 18 struct Edge {
 19     int u, v;
 20     Edge(int u, int v):u(u), v(v){}
 21 };
 22 struct Chain {
 23     int a, b, w;
 24     int lca;
 25 };
 26 struct Fenwick {
 27     int n;
 28     vector<int> c;
 29     void init(int n) {
 30         this->n=n;
 31         c.assign(n+1, 0);
 32     }
 33     int lowbit(int x) {
 34         return x & -x;
 35     }
 36     void add(int x, int v) {
 37         while(x<=n) {
 38             c[x]+=v; x+=lowbit(x);
 39         }
 40     }
 41     int getsum(int x) {
 42         int res=0;
 43         while(x>0) {
 44             res+=c[x]; x-=lowbit(x);
 45         }
 46         return res;
 47     }
 48 } fw1, fw2;
 49 
 50 int n, m;
 51 vector<Edge> edges;
 52 vector<vector<int> > G;
 53 vector<Chain> chain;
 54 vector<int> ln, rn, dep, dp, sum;
 55 vector<vector<int> > fa, arr;
 56 int root, cnt;
 57 void init(int sz) {
 58     edges.clear();
 59     G.assign(sz, vector<int>(0));
 60     chain.resize(sz);
 61     ln.resize(sz); rn.resize(sz); dep.resize(sz); dp.resize(sz); sum.resize(sz);
 62     fa.assign(sz, vector<int>(20));
 63     arr.assign(sz, vector<int>(0));
 64     fw1.init(sz<<1); fw2.init(sz<<1);
 65 }
 66 void addEdge(int u, int v) {
 67     edges.push_back(Edge(u, v));
 68     G[u].push_back(edges.size()-1);
 69 }
 70 void dfs1(int u) {
 71     ln[u]=++cnt;
 72     for(int k=1; k<20; k++) fa[u][k]=fa[fa[u][k-1]][k-1];
 73     for(int i : G[u]) {
 74         Edge & e=edges[i];
 75         if(e.v==fa[u][0]) continue;
 76         fa[e.v][0]=u;
 77         dep[e.v]=dep[u]+1;
 78         dfs1(e.v);
 79     }
 80     rn[u]=++cnt;
 81 }
 82 int lca(int u, int v) {
 83     if(dep[u]<dep[v]) swap(u, v);
 84     for(int k=19; k>=0; k--) {
 85         if(dep[fa[u][k]]>=dep[v]) {
 86             u=fa[u][k];
 87         }
 88     }
 89     if(u==v) return u;
 90     for(int k=19; k>=0; k--) {
 91         if(fa[u][k]!=fa[v][k]) {
 92             u=fa[u][k]; v=fa[v][k];
 93         }
 94     }
 95     return fa[u][0];
 96 }
 97 void dfs2(int u) {
 98     dp[u]=sum[u]=0;
 99     for(int i : G[u]) {
100         Edge & e=edges[i];
101         if(e.v==fa[u][0]) continue;
102         dfs2(e.v);
103         sum[u]+=dp[e.v];
104     }
105     dp[u]=sum[u];
106     for(int i : arr[u]) {
107         Chain & c=chain[i];
108         int tmp=fw1.getsum(ln[c.a])+fw1.getsum(ln[c.b])
109             -fw2.getsum(ln[c.a])-fw2.getsum(ln[c.b])+sum[u];
110         dp[u]=max(dp[u], tmp+c.w);
111     }
112     fw1.add(ln[u], sum[u]); fw1.add(rn[u], -sum[u]);
113     fw2.add(ln[u], dp[u]); fw2.add(rn[u], -dp[u]);
114 }
115 int main() {
116 #ifndef ONLINE_JUDGE
117     freopen("in", "r", stdin);
118     //freopen("out", "w", stdout);
119 #endif
120     int T;
121     scanf("%d", &T);
122     while(T--) {
123         scanf("%d%d", &n, &m);
124         init(n+1);
125         for(int i=1; i<n; i++) {
126             int a, b;
127             scanf("%d%d", &a, &b);
128             addEdge(a, b);
129             addEdge(b, a);
130         }
131         root=1; cnt=0; dep[root]=0; fa[root][0]=root; dfs1(root);
132         for(int i=0; i<m; i++) {
133             scanf("%d%d%d", &chain[i].a, &chain[i].b, &chain[i].w);
134             chain[i].lca=lca(chain[i].a, chain[i].b);
135             arr[chain[i].lca].push_back(i);
136         }
137         dfs2(root);
138         printf("%d\n", dp[root]);
139     }
140     return 0;
141 }
hdu 5293

 

[2015hdu多校联赛补题]hdu5293 Tree chain problem

标签:

原文地址:http://www.cnblogs.com/shjwudp/p/4697045.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!