HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca
Annoying problem
题目连接:
http://acm.hdu.edu.cn/showproblem.php?pid=5293
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
Input
The input consists of several test cases. The first line of input gives the number of test cases T (T<=10).
For each tests:
First line two positive integers n, m.(1<=n,m<=100000)
The following (n - 1) lines contain 2 integers ai bi denoting an edge between vertices ai and bi (1≤ai,bi≤n),
Next m lines each three numbers u, v and val(1≤u,v≤n,0<val<1000), represent the two end points and the weight of a tree chain.
Output
For each tests:
A single integer, the maximum number of paths.
Sample Input
1
7 3
1 2
1 3
2 4
2 5
3 6
3 7
2 3 4
4 5 3
6 7 3
Sample Output
6
Hint
题意
给你一棵树,树上有n个点。
然后给你m条链,然后让你选择一些不相交的链,使得权值和最大。(每条链都有权值)
题解:
树形dp+dfs序+树状数组
首先想到的一点用dp[i]表示以i为根的子树最大值。
所给你的链只用考虑在lca这个点拿。
一个辅助数组sum[i]表示i点儿子的所有dp值的和。
然后dp方程就很显然了:
1.如果i点不拿任何链,那么dp[i]=sum[i]
2.如果i点拿了一条链,那么dp[i]=sum[i]+dp[v]+w,dp[v]是以那条链中的某个节点为父亲的点的dp值。
比较显然的发现dp[v] = sum[k] - dp[k],k即为那条链上的点。
然后这个东西按照dfs序去维护一个树状数组就好了。
代码
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+7;
const int maxm = 25;
struct node
{
int l,r,w;
node(int l=0,int r=0,int w=0):l(l),r(r),w(w){}
};
vector<int>E[maxn];
vector<node>query[maxn];
int n,m,x,y,z,dp[maxn],in[maxn],out[maxn],deep[maxn],lca[maxn][maxm],cnt,sum[maxn];
struct Bit
{
int a[maxn];
void init(){memset(a,0,sizeof(a));}
int lowbit(int x){return x&(-x);}
void update(int x,int v)
{
for(int i=x;i<maxn;i+=lowbit(i))
a[i]+=v;
}
int get(int x)
{
int ans=0;
for(int i=x;i;i-=lowbit(i))
ans+=a[i];
return ans;
}
}T;
void init()
{
cnt=1;
for(int i=0;i<maxn;i++)
E[i].clear(),query[i].clear();
T.init();
memset(deep,0,sizeof(deep));
memset(lca,0,sizeof(lca));
memset(dp,0,sizeof(dp));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(sum,0,sizeof(sum));
}
void dfs(int x,int p)
{
in[x]=cnt++;
for(int i=0;i<E[x].size();i++)
{
int v = E[x][i];
if(v==p)continue;
deep[v]=deep[x]+1;
lca[v][0]=x;
for(int j=1;j<maxm;j++)
{
int fa = lca[v][j-1];
if(fa==0)continue;
lca[v][j]=lca[fa][j-1];
}
dfs(v,x);
}
out[x]=cnt++;
}
int up(int x,int d)
{
for(int i=maxm-1;i>=0;i--)
{
if(d<(1<<i))continue;
x=lca[x][i];
d-=(1<<i);
}
return x;
}
int Lca(int x,int y)
{
if(deep[x]>deep[y])swap(x,y);
y=up(y,deep[y]-deep[x]);
if(x==y)return x;
for(int i=maxm-1;i>=0;i--)
{
if(lca[x][i]!=lca[y][i])
x=lca[x][i],y=lca[y][i];
}
return lca[x][0];
}
void dfs2(int x,int fa)
{
for(int i=0;i<E[x].size();i++)
{
int v = E[x][i];
if(v==fa)continue;
dfs2(v,x);
sum[x]+=dp[v];
}
dp[x]=sum[x];
for(int i=0;i<query[x].size();i++)
{
int l=query[x][i].l;
int r=query[x][i].r;
int w=query[x][i].w;
dp[x]=max(dp[x],sum[x]+T.get(in[r])+T.get(in[l])+w);
}
T.update(in[x],sum[x]-dp[x]),T.update(out[x],dp[x]-sum[x]);
}
void solve()
{
init();
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
E[x].push_back(y);
E[y].push_back(x);
}
dfs(1,0);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
query[Lca(x,y)].push_back(node(x,y,z));
}
dfs2(1,0);
cout<<dp[1]<<endl;
}
int main()
{
int t;scanf("%d",&t);
while(t--)solve();
return 0;
}
HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca的更多相关文章
- HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- 刷题总结——Tree chain problem(HDU 5293 树形dp+dfs序+树状数组)
题目: Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There ar ...
- POJ 3321:Apple Tree + HDU 3887:Counting Offspring(DFS序+树状数组)
http://poj.org/problem?id=3321 http://acm.hdu.edu.cn/showproblem.php?pid=3887 POJ 3321: 题意:给出一棵根节点为1 ...
- HDU 3887:Counting Offspring(DFS序+树状数组)
http://acm.hdu.edu.cn/showproblem.php?pid=3887 题意:给出一个有根树,问对于每一个节点它的子树中有多少个节点的值是小于它的. 思路:这题和那道苹果树是一样 ...
- POJ 2763"Housewife Wind"(DFS序+树状数组+LCA)
传送门 •题意 一对夫妇居住在 xx村庄,给村庄有 $n$ 个小屋: 这 $n$ 个小屋之间有双向可达的道路,不会出现环,即所构成的图是个树: 从 $a_i$ 小屋到 $b_i$ 小屋需要花费 $w_ ...
- BZOJ 2819: Nim( nim + DFS序 + 树状数组 + LCA )
虽然vfleaking好像想卡DFS...但我还是用DFS过了... 路径上的石堆异或和=0就是必败, 否则就是必胜(nim游戏). 这样就变成一个经典问题了, 用DFS序+BIT+LCA就可以在O( ...
- Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+ 树状数组或线段树
C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...
- Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组
C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...
随机推荐
- c++中指针常量,常指针,指向常量的常指针区分
const char * myPtr = &char_A;//指向常量的指针 char * const myPtr = &char_A;//常量的指针 const char * con ...
- ubuntu下中文输入法的配置,建议用fcitx
Fcitx [ˈfaɪtɪks] 是一个支持扩展的输入法框架.它有自己维护的三个输入法,拼音,区位和码表:还支持其他引擎,rime 中州韵,google-pinyin,sunpinyin.Fcitx ...
- Python os模块和sys模块 操作系统的各种接口
一.os模块 这个模块提供了一个便携式去使用操作系统的相关功能,如果只是想操作路径,请参阅os.path模块. ''' os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 ...
- nginx解析带中文的url重定向之后404问题
首先,有这样一个需求:一个系统的图片存储是放在upyun上的,现在有个客户需要本地化部署,所以需要将图片进行本地存储.为了兼容,图片存储的路径格式保持和在upyun上的存储路径一致.在upyun上的存 ...
- BootStarp的form表单的基本写法
代码如下: <!DOCTYPE html> <html> <head> <title>BootStrap的基础入门</title> < ...
- ntp 控制报文
//make the procedure into block//2014.7.23 OK//#include "CSocket.h" #define NTP_SERVER_IP ...
- hdu 5912(迭代+gcd)
Fraction Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Su ...
- Linux 基础——权限管理命令chown、chgrp
一.chown命令与chgrp命令的作用 有时你需要改变文件或目录的属主,比如有人离职或开发人员创建了一个在测试或生产环境中需要归属在系统账户下的应用.Linux提供了两个命令来实现这个功能:chow ...
- JavaScript“并非”一切皆对象
上一篇:<函数声明和函数表达式--函数声明和函数表达式的异同> p{font-size:14px; } 写在前面 网上非常多都在说"JavaScript一切皆对象",那 ...
- 【转】EventBus 3.0使用详解
原文:https://www.jianshu.com/p/f9ae5691e1bb 01 前言 当我们进行项目开发的时候,往往是需要应用程序的各组件.组件与后台线程间进行通信,比如在子线程中进行请求数 ...