回滚树形dp(按dfs序dp)——hdu6035
本题前面的操作别的博客里都有。难点在于颜色ci的贡献,如何一次dfs求出答案
先来考虑如何在一次dfs中单独对颜色i进行计算
用遍历dfs序的方式,在深搜过程中,碰到带有颜色 i 的点 u,u每个颜色不为i的子节点v都会贡献一个联通块,
v的贡献的联通块大小是size[v]-sum{v中层次最高的以颜色i的结点为根的子树大小}
那我们要先求出v中层次最高的以颜色i的结点为根的子树大小,所以用sum表示目前为止颜色i的所有子树的大小,用last存下v进入dfs前的sum,即不算v下颜色i的子树时的sum
到v中去dfs,然后把这些子树的大小加到sum中
当遍历完v的所有子树后,我们会发现 sum-last 就是v下层次最高的以颜色i的结点为根的子树大小的总和
那么v贡献出的联通块大小就是 k = size[v]-(sum-last)
然后去u的下一棵子树v'进行同样的操作,直到遍历完u的所有子树,此时sum已经变成了到u为止(不包含u)的以颜色i为根的子树大小之和
为了计算u的颜色为i的祖先,需要把u也并入sum里,那么只需要在sum里加入u自己,再加上所有v贡献的联通块即可
现在已经维护完所有的信息,可以推出u的dfs,往上回滚求出u的祖先结点的信息
再来考虑如何在一次dfs中对所有出现的颜色进行计算,
我们可以在上面的递归中发现,每中颜色在求贡献只用到了size[],还有每种颜色对应的sum,那么用sum[c]数组来维护颜色c代表的sum即可,就可以在一次dfs中维护多种颜色的贡献
本题和虚树有些类似的地方,首先把每种颜色当成是一个询问,就类似虚树的询问了
然后是回滚dfs的过程,自叶子往上求(其实是按照dfs序)的方式:在初次碰到u时记录进入dfs前的状态,然后dfs处理完其所有子节点的状态后再来计算u的状态
#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define maxn 200005
#define ll long long ll ans,color[maxn],size[maxn],sum[maxn];
vector<int>G[maxn]; void dfs1(int u,int pre){
size[u]=;
for(int i=;i<G[u].size();i++){
int v=G[u][i];
if(v==pre)continue;
dfs1(v,u);
size[u]+=size[v];
}
} //这个树形dp最重要的是理解sum[]数组的含义,sum[x]的更新像虚树的加边一样是自叶子节点往上回滚的
void dfs2(int u,int pre){
ll other=;//other表示为size[u]减去u下所有最高的以color[u]为根的大小
for(int i=;i<G[u].size();i++){
int v=G[u][i];
if(v==pre)continue;
ll last=sum[color[u]];//记录前前面子树里颜色u的子树(虚树)里的值
dfs2(v,u);
ll diff=sum[color[u]]-last;//v的子树里颜色为color[u]的个数
//v树下不包含color[u]的联通块的大小
ans+=(size[v]-diff-)*(size[v]-diff)/;
other+=size[v]-diff;
}
sum[color[u]]+=other+;//+1是因为u本身也是color[u]
}
int f[maxn],tot;
int main(){
ll n,t=;
while(cin>>n){
++t;
for(int i=;i<=n;i++)G[i].clear();
memset(f,,sizeof f);
tot=; for(int i=;i<=n;i++){
scanf("%d",&color[i]);
f[color[i]]=;
}
for(int i=;i<=n;i++)tot+=f[i];
for(int i=;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
} if(tot==){
printf("Case #%d: %lld\n",t,n*(n-)/);
continue;
} memset(size,,sizeof size);
memset(sum,,sizeof sum); ans=;
dfs1(,);dfs2(,);
for(int i=;i<=n;i++)
if(f[i])
ans+=(n-sum[i])*(n-sum[i]-)/;
ll tmp=(n-)*n/*tot;
printf("Case #%d: %lld\n",t,tmp-ans); }
}
回滚树形dp(按dfs序dp)——hdu6035的更多相关文章
- BZOJ 2286: [Sdoi2011]消耗战 虚树 树形dp 动态规划 dfs序
https://www.lydsy.com/JudgeOnline/problem.php?id=2286 wa了两次因为lca犯了zz错误 这道题如果不多次询问的话就是裸dp. 一棵树上多次询问,且 ...
- Codeforces Round #358 (Div. 2) A B C 水 水 dfs序+dp
A. Alyona and Numbers time limit per test 1 second memory limit per test 256 megabytes input standar ...
- HDU 1501 Zipper(DP,DFS)
意甲冠军 是否可以由串来推断a,b字符不改变其相对为了获取字符串的组合c 本题有两种解法 DP或者DFS 考虑DP 令d[i][j]表示是否能有a的前i个字符和b的前j个字符组合得到c的前i+j ...
- hdu3974 Assign the task dfs序+线段树
There is a company that has N employees(numbered from 1 to N),every employee in the company has a im ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...
- hdu_5293_Tree chain problem(DFS序+树形DP+LCA)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5293 被这题打蹦了,看着题解写的,很是爆炸,确实想不到,我用的DFS序+LCA+树形DP,当然也可以写 ...
- HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca
Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 Description Coco has a tree, w ...
- 【BZOJ2286】消耗战(虚树,DFS序,树形DP)
题意:一棵N个点的树上有若干个关键点,每条边有一个边权,现在要将这些关键点到1的路径全部切断,切断一条边的代价就是边权. 共有M组询问,每组询问有k[i]个关键点,对于每组询问求出完成任务的最小代价. ...
随机推荐
- kubeadm部署多master节点高可用k8s1.16.2
一.架构信息 系统版本:CentOS 7.6 内核:3.10.0‐1062.4.1.el7.x86_64 Kubernetes: v1.16.2 Dockerce: 19.03 推荐硬件配置:2核4 ...
- Buffering Data
We keep telling you that you always need to close your files after you're done writing to them. Here ...
- read more阅读更多,文字超过三行字符后面添加省略号
var text;$('.blog-item').each(function (i) {text = $(this).find('.blog-excerpt').html();if (text.len ...
- go垃圾回收
go垃圾回收 当创建一些变量时,变量有一个确定的生命周期.例如函数中定义的局部变量,当函数退出时变量就不存在了.另外在其他情况下,至少对于编译器来说,这不是那么的明显.例如,某个被函数返回的变量的生命 ...
- HTML5的新增功能有哪些?
HTML5 将成为 HTML.XHTML 以及 HTML DOM 的新标准. 新的功能: 1.用于绘画的 canvas 元素 2.用于媒介回放的 video 和 audio 元素 3.对本地离线存储的 ...
- Web移动端常见问题-摘抄
一.按钮点击时出现黑色背景 解决方法: 1 2 .class { -webkit-tap-highlight-color:rgba(0,0,0,0);} .class { -webkit-appe ...
- Linux文件大小 指令&编程
在工作和日常的编程中时常需要确定文件的大小,一些基本的查看方式在此做一个总结. 一. linux shell环境下 df可以查看一级文件夹大小.使用比例.档案系统及其挂入点,但对文件却无能为力. ...
- JAVA JDBC大数据量导入Mysql
转自https://blog.csdn.net/q6834850/article/details/73726707?tdsourcetag=s_pctim_aiomsg 采用JDBC批处理(开启事务. ...
- Node篇
[Node篇] Node.js中的stream(流)- 基础篇 1)什么是stream(流) 流(stream)在 Node.js 中是处理流数据的抽象接口(abstract interface). ...
- USACO2012 overplanting /// 矩阵切割 递归 oj21547
题目大意: 在农场的任何一个“轴向对齐”的长方形区域(即垂直和水平方向)种植草坪. 现种植了N(1≤ N ≤10)个不同的矩形区域,其中一些甚至可能重叠. Input Multiple test ca ...