(中等) 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 ...
随机推荐
- 用sql server的sql语句算一个empty GUID
在C#中得到一个empty GUID的方法是: Guid id= Guid.Empty; 那么在SQL Server Management Studio中怎样得到一个empty GUID呢? 方法有两 ...
- linux学习的哲学层面的思考-架构
参考:http://blog.chinaunix.net/uid-26119273-id-3356414.html 学习Linux,准备做产品的话,不要把Linux当成了终极目标(当然,这是对应用而言 ...
- 1.1 python 安装(Windows)
1.浏览器输入URL http://www.python.org/download/ https://www.python.org/downloads/release/python-2712/ Win ...
- c++中string的用法
之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必 担心内存是否足够.字符串长度等等,而且作为一个类出现,他集成的操作函数足以完成我们大多数情况下(甚至 ...
- Java利用POI生成Excel强制换行
前一段时间在做一个学校排课系统时,有一个地方需要利用把课程表生成excel汇出给客户,由于之前用excel都只是简单的应用,在单元格里都是用自动换行,而这次可能需要用到手动强制换行. 于是我在网上找了 ...
- JAVA-面向对象--封装
1. 如果一个类中没有定义构造函数,会自动加上一个空参的默认构造函数 如果定义了一个构造函数,默认的空参构造函数就没有了. 2. this 当成员变量与局部变量重名的时候,可以使用this来区分.th ...
- c++绘图软件<一>
准备写一个绘图软件,参考了三层架构(表现层.业务逻辑层.数据访问层). //////////////////////////////////////////////////////////////// ...
- 关于一些url中传递参数有空格问题
1.关于一些url中传递参数有空格问题: url.replace(/ /g, "%20") 从上面的例子中可以看到可以用:replace(/ /g, "%20" ...
- SqlServer 查询死锁,杀死死锁进程
-- 查询死锁 select request_session_id spid, OBJECT_NAME(resource_associated_entity_id) tableName from sy ...
- zookeeper实现分布式锁服务
A distributed lock base on zookeeper. zookeeper是hadoop下面的一个子项目, 用来协调跟hadoop相关的一些分布式的框架, 如hadoop, hiv ...