(中等) 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 ...
随机推荐
- 在idea的maven项目使用el或jstl表达式
必须加上这句: <%@ page isELIgnored="false" %> 否则无法解析el或jstl表达式 <%@ taglib prefix=" ...
- java设计模式案例详解:观察者模式
观察者模式的应用场景: 1. 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变. 2. 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节. 举个例子说明,这个例子讲 ...
- Android中实现滑动翻页—使用ViewFlipper(dp和px之间进行转换)
Android中实现滑动翻页—使用ViewFlipper(dp和px之间进行转换) Android中dp和px之间进行转换 在xml布局文件中,我们既可以设置px,也可以设置dp(或者dip).一般情 ...
- nagios总结
主要功能 网络服务监控(SMTP.POP3.HTTP.NNTP.ICMP.SNMP.FTP.SSH) 主机资源监控(CPU load.disk usage.system logs),也包括Window ...
- cocos2d-x 3.3 显示中文
Resources文件夹下的strings.xml: <dict> <key>targetScore</key> <string>目标分数</st ...
- Centos-ip配置详解
1 搭建好Centos ,我这里是CentOS-6.7-x86_64-minimal 提供一个下载地址 链接:http://pan.baidu.com/s/1nvTUTh3 密码:xewk 2 我是 ...
- Android Studio的使用(十)--读取assets、Raw文件夹下文件,以及menu、drawable文件夹
1.直接在/src/main目录下面新建assets目录 2.接下来即可读取文件 3.读取Raw文件夹下文件也类似.首先在res文件夹下新建raw目录,然后放入需要的文件即可读取. 4.menu和dr ...
- 第13章 Swing程序组件----常用布局管理器
在Swing中,每个组件在容器中都有一个具体的位置和大小,而在容器中摆放各种组件时很难判断其具体位置和大小.布局管理器提供了Swing组件安排.展示在容器中的方法及基本的布局功能. Swing提供的常 ...
- SQL求解两个时间差
sql 求解两个时间差 SELECTDATEDIFF( Second, '2009-8-25 12:15:12', '2009-9-1 7:18:20') --返回相差秒数 SELECTDATEDIF ...
- C#入门经典第九章定义类-1
1.C#中使用class关键字来定义类 class MyClass { //代码部分 } 定义了类之后,就可以在项目中能访问该定义的其他位置对该类进行实例化.默认情况下,类的声明是内部的,即只有当前项 ...