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 ...
随机推荐
- Mysql储存过程1: 设置结束符与储存过程创建
#显示储存过程 show procedure status; #设置结束符 delimiter $; #创建储存过程 create procedure procedure_name() begin - ...
- 31 - gogs安装-git基础
目录 1 Gogs安装 2 Git介绍 3 使用Github仓库 3.1 Git配置 3.2 远程仓库 4 Git基本使用 4.1 创建版本库 4.2 查看工作区状态 4.3 查看修改内容 4.4 查 ...
- go 数据变量和操作符
数据类型 布尔类型 a. var b bool 和 var b bool = true 和 var b = falseb. 操作符 == 和 !=c. 取反操作符: !bd. && 和 ...
- JS时间转换的一个坑位
在做项目的时候,无意发现了一个小东西. new Date('2018-05-15') new Date('2018-5-15') 输出的结果是不同的,相差了8小时.然后让我回忆到之前看的一个时间转换函 ...
- nginx location 指令意义
基本语法:location [=|~|~*|^~] /uri/ { … } = 严格匹配.如果这个查询匹配,那么将停止搜索并立即处理此请求.~ 为区分大小写匹配(可用正则表达式)!~为区分大小写不匹配 ...
- Oracle安装出现报错
报错信息如下: >>> Couldnot execute auto check for display colors using command /usr/bin/xdpyinfo. ...
- .htaccess教程:简介、访问控制、验证、目录浏览控制
一..htaccess简介 1.什么是.htaccess .htaccess是一个纯文本文件,里面存放着Apache服务器配置相关的一些指令,它类似于Apache的站点配置文件,如httpd.conf ...
- POJ 3087 Shuffle'm Up (模拟+map)
题目链接:http://poj.org/problem?id=3087 题目大意:已知两堆牌s1和s2的初始状态, 其牌数均为c,按给定规则能将他们相互交叉组合成一堆牌s12,再将s12的最底下的c块 ...
- PHP下利用PHPMailer
PHPMailer有什么优点? 可运行在任何平台之上 支持SMTP验证 发送邮时指定多个收件人,抄送地址,暗送地址和回复地址:注:添加抄送.暗送仅win平台下smtp方式支持 支持多种邮件编码包括:8 ...
- csu 1553(RMQ+尺取法)
1553: Good subsequence Time Limit: 2 Sec Memory Limit: 256 MBSubmit: 794 Solved: 287[Submit][Statu ...