(中等) HDU 5293 Tree chain problem,树链剖分+树形DP。
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
// ━━━━━━神兽出没━━━━━━
// ┏┓ ┏┓
// ┏┛┻━━━━━━━┛┻┓
// ┃ ┃
// ┃ ━ ┃
// ████━████ ┃
// ┃ ┃
// ┃ ┻ ┃
// ┃ ┃
// ┗━┓ ┏━┛
// ┃ ┃
// ┃ ┃
// ┃ ┗━━━┓
// ┃ ┣┓
// ┃ ┏┛
// ┗┓┓┏━━━━━┳┓┏┛
// ┃┫┫ ┃┫┫
// ┗┻┛ ┗┻┛
//
// ━━━━━━感觉萌萌哒━━━━━━ // 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。的更多相关文章
- HDU 5293 Train chain Problem - 树链剖分(树状数组) + 线段树+ 树型dp
传送门 题目大意: 一颗n个点的树,给出m条链,第i条链的权值是\(w_i\),可以选择若干条不相交的链,求最大权值和. 题目分析: 树型dp: dp[u][0]表示不经过u节点,其子树的最优值,dp ...
- [HDU 5293]Tree chain problem(树形dp+树链剖分)
[HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...
- HDU5293 树链剖分+树形DP
=-=抓住叶节点往上揪 Tree chain problem Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K ...
- HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...
- HDU 5293 Tree chain problem
树状数组 + dp 设$f_i$表示以$i$为根的子树中的能选取的最大和,$sum_x$表示$\sum_{f_y}$ ($y$是$x$的一个儿子),这样子我们把所有给出的链按照两点的$lca$分组, ...
- codeforces 671D Roads in Yusland & hdu 5293 Tree chain problem
dp dp优化 dfs序 线段树 算是一个套路.可以处理在树上取链的问题.
- HDU 5293 Tree chain problem 树形DP
题意: 给出一棵\(n\)个节点的树和\(m\)条链,每条链有一个权值. 从中选出若干条链,两两不相交,并且使得权值之和最大. 分析: 题解 #include <cstdio> #incl ...
- Water Tree CodeForces 343D 树链剖分+线段树
Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...
- [POJ3237]Tree解题报告|树链剖分|边剖
关于边剖 之前做的大多是点剖,其实转换到边剖非常简单. 我的做法是每个点的点权记录其到父亲节点的边的边权. 只要solve的时候不要把最上面的点记录在内就可以了. Tree Description Y ...
随机推荐
- 【裸最小生成树】 模板 poj 1258
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #def ...
- HTML day01基础总结
1.网页的基本元素 文字.图像与超链接. 2.每一个网页元素通常由开始标记.结束标记,以及在这两个标记中的内容所组成. 3.一般结构 <html> <head> <met ...
- UIImageView 的contentMode属性应用
UIImageView 的contentMode这个属性是用来设置图片的显示方式,如居中.居右,是否缩放等,有以下几个常量可供设定:UIViewContentModeScaleToFillUIView ...
- linux的学习系列 7---管道和过滤器
有时候,我们可以把两个命令连起来使用,一个命令的输出作为另一个命令的输入,这就叫做管道.为了建立管道,需要在两个命令之间使用竖线(|)连接. 管道是Linux进程之间一种重要的通信机制:除了管道,还有 ...
- JS-DOM元素灵活查找
用className选择元素 封装成函数 <title>无标题文档</title> <script> /* window.onload=function () { ...
- HDU 3861 The King’s Problem(tarjan连通图与二分图最小路径覆盖)
题意:给我们一个图,问我们最少能把这个图分成几部分,使得每部分内的任意两点都能至少保证单向连通. 思路:使用tarjan算法求强连通分量然后进行缩点,形成一个新图,易知新图中的每个点内部的内部点都能保 ...
- Node.js学习 - Modules
创建模块 当前目录:hello.js, main.js // hello.js exports.world = function() { // exports 对象把 world 作为模块的访问接口 ...
- 逆序一个8bit的2进制数
- USACO Section 1.3 Ski Course Design 解题报告
题目 题目描述 有N座山,每座山都有一个高度,现在由于农夫想避税,所以想把这些山的高度进行一些改变,使得最高的山与最低的山之间的高度差不超过17.每座山最多只能改变一次高度,每次改变高度都会产生一定的 ...
- Linux 部署 Tomcat和JDK
一:安装jdk下载将jdk加压后放到/usr/local目录下: [root@master ~]#chmod 755 jdk-6u5-linux-x64.bin [root@master ~]# ./ ...