题目链接:https://vjudge.net/problem/HDU-6035

题目大意:

  多样例输入。

  对于每一个样例,给出 n \((2 \le n \le 200000)\) 个结点的一棵树,各个节点都有各自的颜色 \(c_i  (1 \le c_i \le n)\),树上任意两点之间的路径的权值为该路径经过的不同颜色的结点数,求树上所有两点路径的权值之和。

知识点:  树、DFS

解题思路:

  求树上所有的两点路径的权值之和,可以转化为求各个颜色在各条路径中的贡献值(即该颜色能够为树上的各条路径增加的权值的总和,也可以理解成是该颜色在多少条路径中出现)。但是,并没有非常好的方法可以直接求出这个总的贡献值,于是,我们可以反过来求:各个颜色在多少条路径中没有出现。

  如图1所示,树上所有的红色结点将整棵树分成了 5 个联通块(笔者已用 1~5 标出),则这五个联通块里面的所有路径显然都没有经过红色结点。其实这些联通块也可以看成是一棵子树,对于一棵有 n 个结点的树,树上所有路径数为 \(\frac{n(n-1)}{2}\) 1

  那么,我们所要求的答案其实就是\(\frac{NumberOfColors \times n \times (n-1)}{2}\) - 没有经过各个颜色的所有路径数

  对于每一种颜色,没有经过该种颜色的路径可以分成两类:

  1、从树根以下,到第一次接触颜色点之前的这一联通块的路径(如图1中的第1块);

  2、颜色点之间和颜色点以下直到叶子的联通块(如图1中的第2~5块)。

  只要算出这两种路径的总数,即可求出答案,但此题的实现并不简单,请看代码及注释:

AC代码:

 #include <cstdio>
#include <vector>
#include <set> using namespace std;
typedef long long ll;
const int maxn=+; int color[maxn];//记录各个结点的颜色
ll sum[maxn];//精髓所在
ll sizes[maxn];//记录各个结点以下的结点数
vector<int> tree[maxn];//记录树
set<int> col;
ll ans;
void find_size(int fa,int gfa){//找出各点的 sizes[i]
sizes[fa]=;
for(int i=;i<tree[fa].size();i++){
if(tree[fa][i]==gfa) continue;
find_size(tree[fa][i],fa);
sizes[fa]+=sizes[tree[fa][i]];
}
}
void find_ans(int fa,int gfa){
ll tmp=;
if(sum[color[fa]]!=){
//此处 sum[color[fa]] 记录的是目前已知的从各个分枝的第一个颜色为 color[fa] 的点到叶子的结点数,那么当最后求出这个值以后,上文提及的第一类路径的结点数即为 n-sum[i]
tmp=sum[color[fa]];
sum[color[fa]]=;
/* ***************** */
}
for(int i=;i<tree[fa].size();i++){
if(tree[fa][i]==gfa) continue;
find_ans(tree[fa][i],fa);
//此处sum[color[fa]]用于求从 tree[fa][i] 这个结点出发到下一个颜色为 color[fa] 或者叶子的联通块的结点数
//请注意上下两处划线处的代码
ans-=(sizes[tree[fa][i]]-sum[color[fa]])*(sizes[tree[fa][i]]-sum[color[fa]]-)/;
sum[color[fa]]=;
/* ***************** */
}sum[color[fa]]=sizes[fa]+tmp;
}
int main(){
int n,a,b;
int kase=;
while(scanf("%d",&n)==){
col.clear();
for(int i=;i<=n;i++){
sum[i]=;
tree[i].clear();
}
for(int i=;i<=n;i++){
scanf("%d",&color[i]);
col.insert(color[i]);
}
ans=(ll)col.size()*n*(n-)/;
for(int i=;i<n;i++){
scanf("%d%d",&a,&b);
tree[a].push_back(b);
tree[b].push_back(a);
}find_size(,);
find_ans(,);
set<int>::iterator pt=col.begin();
for(;pt!=col.end();pt++){
int cl=*pt;
ans-=(n-sum[cl])*(n-sum[cl]-)/;
}
printf("Case #%d: %lld\n",kase++,ans);
}return ;
}

  

  

1、n(n-1)/2——此处的公式可能会挂,原因不明......

HDU6035 Colorful Tree的更多相关文章

  1. hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。

    /** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...

  2. hdu-6035 Colorful Tree

    题目意思是计算所有路径(n*(n-1)/2)经过的不同颜色的数目和. 这个数目和可以转化为每种颜色经过的路径数目的求和,而这个求和又等价于颜色总数*n*(n-1)/2-没有经过某种颜色的边的数量的求和 ...

  3. 【树形dp】hdu6035 Colorful Tree

    非常棒的题解,我就不复述了:http://blog.csdn.net/Bahuia/article/details/76141574 O(n) #include<cstdio> #incl ...

  4. HDU-6035 Colorful Tree(树形DP) 2017多校第一场

    题意:给出一棵树,树上的每个节点都有一个颜色,定义一种值为两点之间路径中不同颜色的个数,然后一棵树有n*(n-1)/2条 路径,求所有的路径的值加起来是多少. 思路:比赛的时候感觉是树形DP,但是脑袋 ...

  5. HDU6035:Colorful Tree(树形DP)

    传送门 题意 给出一棵最小生成树及每个节点的颜色,询问\(\frac{n(n-1)}2\)条路径的权值和,一条路径的权值为该路径的颜色种数 分析 勉强理解了ftae的做法,但是代码还是不太会,还是太弱 ...

  6. 2017 Multi-University Training Contest - Team 1 1003&&HDU 6035 Colorful Tree【树形dp】

    Colorful Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

  7. AtCoder Beginner Contest 133 F Colorful Tree

    Colorful Tree 思路: 如果强制在线的化可以用树链剖分. 但这道题不强制在线,那么就可以将询问进行差分,最后dfs时再计算每个答案的修改值, 只要维护两个数组就可以了,分别表示根节点到当前 ...

  8. HDU 6035 - Colorful Tree | 2017 Multi-University Training Contest 1

    /* HDU 6035 - Colorful Tree [ DFS,分块 ] 题意: n个节点的树,每个节点有一种颜色(1~n),一条路径的权值是这条路上不同的颜色的数量,问所有路径(n*(n-1)/ ...

  9. [HDU6793] Tokitsukaze and Colorful Tree

    题目 又是一个条历新年,窗前的灼之花又盛开了. 时隔多年,现在只有这一棵树上盛开着残存的 \(n\) 朵灼之花了. 尽管如此,这些灼之 花仍散发出不同色彩的微弱的光芒. 灼之花的生命极为短暂,但它的花 ...

随机推荐

  1. Mozilla开始推送Firefox Preview 5.0版 支持画中画特性

    Mozilla 发布了 5.0 版本的 Firefox Preview 浏览器,根据 GitHub 上的发布说明,这次更新带来了一系列新的改进.其中包含对五个新的附加组件的支持,引入了对 Progre ...

  2. 获取系统DPI、系统显示比例等

    using System; using System.Drawing; using System.Runtime.InteropServices; namespace XYDES { public c ...

  3. 从「Hello World」说起

    标签: node模块 从一个简单「hello world」程序对 node.js 有个感性的认识. const http = requier ('http'); const pathname = '1 ...

  4. 20171016 Python的安装

    Linux: wget https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tgz.asc tar zxvf Python-2.7.13.tg ...

  5. 数学--数论--Alice and Bob (CodeForces - 346A )推导

    It is so boring in the summer holiday, isn't it? So Alice and Bob have invented a new game to play. ...

  6. The Preliminary Contest for ICPC Asia Xuzhou 2019 徐州网络赛 D Carneginon

    Carneginon was a chic bard. But when he was young, he was frivolous and had joined many gangs. Recen ...

  7. jmeter正则表达式提取多个数据/一组数据时,应该怎么做——debug sampler的使用

    背景:今天有个接口需要借助前面接口产生的一组ids数据,来作为入参使用,但是之前都是提取单个接口,所以到底怎么提取接口,遇到了很大的问题,按照多方查取资料都没有成功,最终在一个不相关帖子的最后一句话被 ...

  8. LeetCode 98. 验证二叉搜索树 | Python

    98. 验证二叉搜索树 题目来源:https://leetcode-cn.com/problems/validate-binary-search-tree 题目 给定一个二叉树,判断其是否是一个有效的 ...

  9. ES[7.6.x]学习笔记(六)分析器

    在前面的章节中,我们给大家介绍了索引中的映射类型,也就是每一个字段都有一个类型,比如:long,text,date等.这和我们的数据库非常的相似,那么它的不同之处是什么呢?对了,就是全文索引,在ES当 ...

  10. jQuery如何使用键盘事件,按住空格键完成进度条效果,并终止键盘事件

    jQuery使用键盘事件 keyup:键盘抬起时 keydown:键盘按下时 keypress:键盘按住时 运行下列代码,可以看效果 $(document).keyup(function () { c ...