Problem Description
 
Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.
There are m chain on the tree, Each chain has a certain weight. Coco would like to pick out some chains any two of which do not share common vertices.
Find out the maximum sum of the weight Coco can pick
 
  挺不错的一道题目,15年多校的第一场的题目,不过我太弱,比赛的时候没能想出来,赛后想了一天才把他过掉。
  刚开始的时候想法是dfs序,然后dp就好,但是好像有点问题,然后就GG了。。。
  然后想到了树形DP,想了很久才会。
  首先对于每个链,找到他两个端点的LCA,然后把这个链加到他们的LCA那里去。
  dp[i][0]表示对于i这个点,不选LCA为i的链则这颗以i为根的树最大能得到多少,dp[i][1]就是在i的链和不选i的链中最大的那一个。
  然后就是树形DP加上状态转移,dp[i][0]的话状态转移很简单,就是i的所有儿子的dp[i][1]的和就好,但是dp[i][1]这里卡了我老长时间,因为要把所有链上的点的所有非链儿子的dp[i][1]加在一起才行,然后后来想到了用减的方法算,对于某个链上的点x,他的非链儿子的dp[x][1]的和就是他的dp[x][0]减去链上儿子的dp[x][1]就好,所以就是先算出链上所有点的dp[i][0]的和,然后减去除了i的儿子之外链上所有点的dp[i][1]的和就好,再加上除了这个链之外的儿子,就能得到结果了。
  然后算和的话用树链剖分就行。
  好像动态树的话算起来更简单,但是我并不会。。。
 
代码如下:
// ━━━━━━神兽出没━━━━━━
// ┏┓ ┏┓
// ┏┛┻━━━━━━━┛┻┓
// ┃ ┃
// ┃ ━ ┃
// ████━████ ┃
// ┃ ┃
// ┃ ┻ ┃
// ┃ ┃
// ┗━┓ ┏━┛
// ┃ ┃
// ┃ ┃
// ┃ ┗━━━┓
// ┃ ┣┓
// ┃ ┏┛
// ┗┓┓┏━━━━━┳┓┏┛
// ┃┫┫ ┃┫┫
// ┗┻┛ ┗┻┛
//
// ━━━━━━感觉萌萌哒━━━━━━ // Author : WhyWhy
// Created Time : 2015年07月22日 星期三 13时55分13秒
// File Name : 1006.cpp #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int MaxN=; struct Edge
{
int to,next;
}; struct Lian
{
int u,v;
int cost;
int next;
}; int N,M; Edge E[MaxN<<];
int head[MaxN],Ecou; Lian L[MaxN];
int Lhead[MaxN],Lcou; int fa[MaxN],dep[MaxN],son[MaxN],siz[MaxN],top[MaxN],w[MaxN];
int Tcou; int C_max[MaxN],C_wu[MaxN]; void init()
{
Ecou=;
Lcou=;
Tcou=;
w[]=;
top[]=;
memset(Lhead,-,sizeof(Lhead));
memset(head,-,sizeof(head));
} void addEdge(int u,int v)
{
E[Ecou].to=v;
E[Ecou].next=head[u];
head[u]=Ecou++;
} int lca(int a,int b)
{
while()
{
if(top[a]==top[b])
return dep[a]<dep[b] ? a : b;
else if(dep[top[a]]>dep[top[b]])
a=fa[top[a]];
else
b=fa[top[b]];
}
} void addLian(int u,int v,int c)
{
int h=lca(u,v); L[Lcou].u=u;
L[Lcou].v=v;
L[Lcou].cost=c;
L[Lcou].next=Lhead[h];
Lhead[h]=Lcou++;
} void dfs1(int u,int pre,int d)
{
int v; dep[u]=d;
fa[u]=pre;
siz[u]=;
son[u]=-; for(int i=head[u];i!=-;i=E[i].next)
if(E[i].to!=pre)
{
v=E[i].to;
dfs1(v,u,d+);
siz[u]+=siz[v]; if(son[u]==- || siz[son[u]]<siz[v])
son[u]=v;
}
} void dfs2(int u)
{
if(son[u]==-)
return; top[son[u]]=top[u];
w[son[u]]=++Tcou; dfs2(son[u]); int v; for(int i=head[u];i!=-;i=E[i].next)
if(E[i].to!=son[u] && E[i].to!=fa[u])
{
v=E[i].to;
top[v]=v;
w[v]=++Tcou;
dfs2(v);
}
} void TL_init()
{
dfs1(,-,);
dfs2();
memset(C_max,,sizeof(C_max));
memset(C_wu,,sizeof(C_wu));
} inline int lowbit(int x)
{
return x&(-x);
} int sum(int x,int C[])
{
int ret=; while(x>)
{
ret+=C[x];
x-=lowbit(x);
} return ret;
} void add(int x,int d,int C[])
{
while(x<=N)
{
C[x]+=d;
x+=lowbit(x);
}
} int query(int u,int v,int C[])
{
int f1=top[u],f2=top[v];
int ret=; while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(u,v);
} ret+=sum(w[u],C)-sum(w[f1]-,C);
u=fa[f1];
f1=top[u];
} if(dep[u]>dep[v])
swap(u,v); ret+=sum(w[v],C)-sum(w[u]-,C); return ret;
} void update(int u,int ut,int C[])
{
add(w[u],ut,C);
} int dp[MaxN][]; void dfs(int u)
{
int v;
int ans=;
int maxn=,tsum1,tsum2; for(int i=head[u];i!=-;i=E[i].next)
if(E[i].to!=fa[u])
{
dfs(E[i].to);
ans+=dp[E[i].to][];
} for(int h=Lhead[u];h!=-;h=L[h].next)
{
tsum1=query(L[h].u,L[h].v,C_wu);
tsum2=query(L[h].u,L[h].v,C_max);
maxn=max(maxn,tsum1-tsum2+ans+L[h].cost);
} maxn=max(maxn,ans);
dp[u][]=ans;
dp[u][]=maxn; update(u,ans,C_wu);
update(u,maxn,C_max);
} int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout); int T;
int a,b,c; scanf("%d",&T); while(T--)
{
scanf("%d %d",&N,&M);
init(); for(int i=;i<N;++i)
{
scanf("%d %d",&a,&b);
addEdge(a,b);
addEdge(b,a);
} TL_init(); while(M--)
{
scanf("%d %d %d",&a,&b,&c);
addLian(a,b,c);
} memset(dp,,sizeof(dp));
dfs(); printf("%d\n",dp[][]);
} return ;
}

(中等) HDU 5293 Tree chain problem,树链剖分+树形DP。的更多相关文章

  1. HDU 5293 Train chain Problem - 树链剖分(树状数组) + 线段树+ 树型dp

    传送门 题目大意: 一颗n个点的树,给出m条链,第i条链的权值是\(w_i\),可以选择若干条不相交的链,求最大权值和. 题目分析: 树型dp: dp[u][0]表示不经过u节点,其子树的最优值,dp ...

  2. [HDU 5293]Tree chain problem(树形dp+树链剖分)

    [HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...

  3. HDU5293 树链剖分+树形DP

    =-=抓住叶节点往上揪 Tree chain problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K ...

  4. HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...

  5. HDU 5293 Tree chain problem

    树状数组 + dp 设$f_i$表示以$i$为根的子树中的能选取的最大和,$sum_x$表示$\sum_{f_y}$  ($y$是$x$的一个儿子),这样子我们把所有给出的链按照两点的$lca$分组, ...

  6. codeforces 671D Roads in Yusland & hdu 5293 Tree chain problem

    dp dp优化 dfs序 线段树 算是一个套路.可以处理在树上取链的问题.

  7. HDU 5293 Tree chain problem 树形DP

    题意: 给出一棵\(n\)个节点的树和\(m\)条链,每条链有一个权值. 从中选出若干条链,两两不相交,并且使得权值之和最大. 分析: 题解 #include <cstdio> #incl ...

  8. Water Tree CodeForces 343D 树链剖分+线段树

    Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...

  9. [POJ3237]Tree解题报告|树链剖分|边剖

    关于边剖 之前做的大多是点剖,其实转换到边剖非常简单. 我的做法是每个点的点权记录其到父亲节点的边的边权. 只要solve的时候不要把最上面的点记录在内就可以了. Tree Description Y ...

随机推荐

  1. sql-删除delete涉及到三个表,这个时候就要使用from,比如这样

    delete y from dbo.XZXK_BANJIE b ,YJDC_YELLOWRED_CONTENT y , dbo.XZXK_SHOULI s where b.shoulioid=s.sh ...

  2. 转 awk 使用方法

    Shell编程-awk 简介 awk 是一种对立的编程语言,集成于所有UNIX/Linux中,这个名字是它创建者的名字首字母组成的 Alfred Aho,Peter Weinberger, and B ...

  3. jquery的校验规则的方法

    //validate 选项*********************************************************** $("form").validat ...

  4. Break on _NSLockError() to debug.

    *** -[NSCondition dealloc]: condition (<NSCondition: 0x1039a450> '(null)') deallocated while s ...

  5. 学习笔记——策略模式Strategy

    策略模式,与模板模式一样,都是为了将接口和算法实现解耦,但策略模式更主要是整体算法的替换,而模板模式主要是流程一致,部分算法的替换. 个人理解为,一般算法替换,使用策略模式,当算法流程一致,可以提取为 ...

  6. ubuntu apache2 流量限制模块

    mod-bw is an Apache 2 module provided to solve the problem of limiting users’ and virtual hosts’ ban ...

  7. 【从汉字中提取数字】不用公式,不用VBA,如此简单的方法你是否用过?

    转自:http://huaban.com/pins/19664410 具体操作过程请看附图动画:

  8. Magento首页显示产品

    Magento首页显示产品     经常用的比较琐碎,上官网发现一个稍微全一点的不过没有针对 具体使用过程中遇到的情况进行修正  这边只做一个备忘吧   (细节问题 按个别情况进行修改即可) New  ...

  9. jquery控制audio的播放与暂停

    <audio id="audio" src='music.mp3'></audio> <script type="type/javascri ...

  10. linux下libreoffice安装测试

    一.Linux安装 wget http://download.documentfoundation.org/libreoffice/stable/4.4.6/rpm/x86_64/LibreOffic ...