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 ...
随机推荐
-
Xcode5 + phoneGap2.9搭建ios开发环境-配置-测试-归档上传/phoneG...
前言: 小弟是做JAVA/Android的第一次搞这个ios,公司有mobile项目是使用phoneGap开发的,需要开发ios版本.什么都不会只能一点一点琢磨了……大神越过…… 原文链接:http: ...
-
testng对失败时截图处理
1.截图类: public class ScreenShot { public WebDriver driver; public ScreenShot(WebDriver driver) { this ...
-
URAL 1057. Amount of Degrees(数位DP)
题目链接 我看错题了...都是泪啊,不存在3*4^2这种情况...系数必须为1... #include <cstdio> #include <cstring> #include ...
-
java基础接口练习
1.编写2个接口:InterfaceA和InterfaceB:在接口InterfaceA中有个方法voidprintCapitalLetter():在接口InterfaceB中有个方法void pri ...
-
iOS - UIAlertView
前言 NS_CLASS_DEPRECATED_IOS(2_0, 9_0, "UIAlertView is deprecated. Use UIAlertController with a p ...
-
VBA解密
1.关闭要解密的excel文件,新建一个excel文件 2.打开新建的这个Excel,按下alt+F11,打开vb界面,新建一个模块,如图所示 3.将代码复制到这个模块中,代码如下:Private S ...
-
ADB错误“more than one device and emulator”(转)
当我连着手机充电的时候,启动模拟器调试,执行ADB指令时,报错.C:\Users\gaojs>adb shellerror: more than one device and emulatorC ...
-
php 多维数组如何用foreach遍历修改其中的一个值
数组: array(6) { [0]=> array(11) { ["id"]=> string(2) "76" ["topic_id&q ...
-
C++对文件进行加密解密
1. 起因: 需要对游戏资源进行加密 2. 解决方案: 通过网络查询,xxtea是一款轻量级的加密工具,使用简单方便 3. 加密解密 xxtea只有两个函数,加密:xxtea_encrypt 解密:x ...
-
IntelliJ IDEA 2017.3/2018.1激活与汉化
本文以IntelliJ IDEA 2017.3以及2018.1为例进行讲解.(持续更新:2018年5月28日) 适用版本(其它版本未测试): IntelliJ IDEA 2017.2.6.2017.3 ...