(中等) 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 ...
随机推荐
- WNDCLASS 窗口类结构
Windows 的窗口总是基于窗口类来创建的,窗口类同时确定了处理窗口消息的窗口过程(回调函数). 在创建应用程序窗口之前,必须调用 RegisterClass 函数来注册窗口类.该函数只需要一个参数 ...
- Java Interrupt Related
In Java, the main process can have several threads at a time, but only a few of them can run concurr ...
- php 个推的例子
个推 http://docs.getui.com/server/php/start/ <?php /** * Created by PhpStorm. * User: xiaochao * ...
- android之相机开发
http://blog.csdn.net/jason0539/article/details/10125017 android之相机开发 分类: android 基础知识2013-08-20 22: ...
- 快学Scala-第八章 继承
知识点: 1.扩展类 extends关键字,在定义中给出子类需要而超类没有的字段和方法,或者重写超类的方法. 2.重写方法 在Scala中重写一个非抽象方法必须 override 修饰符 public ...
- 将所需要的图标排成一列组成一张图片,方便管理。li的妙用
我在做一个网站的header 但是视频教学里面将电话图标,微信图标,以及每一个英文字母右边的小点拼成一副图. (图片的名字是top_ioc.png)拼成的整个图片作为li的背景.通过移动就可以分别将每 ...
- PAT (Advanced Level) 1111. Online Map (30)
预处理出最短路再进行暴力dfs求答案会比较好.直接dfs效率太低. #include<cstdio> #include<cstring> #include<cmath&g ...
- mysql笔记4之数据操作
1修改数据 插入:insert into stu(id,name,age,addr) values(2,"李四",44,"重庆"); 2修改某一列 updata ...
- SORT函数的使用方法(转载)
sort函数的用法(转载出处:http://blog.sina.com.cn/s/blog_6439f26f01012xw3.html) 做ACM题的时候,排序是一种经常要用到的操作.如果每次都自己写 ...
- C++读取excel特定行列中的数据
可以通过COM API调用才是正解,不过需要编写COM接口类,Excel对象库的接口太多了……不过可以用工具自动生成. 我最近也在用VC操作Excel,在VC中可以这样做,在任何一个cpp文件中加入下 ...