HDU6035 Colorful Tree
题目链接: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的更多相关文章
- hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。
/** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...
- hdu-6035 Colorful Tree
题目意思是计算所有路径(n*(n-1)/2)经过的不同颜色的数目和. 这个数目和可以转化为每种颜色经过的路径数目的求和,而这个求和又等价于颜色总数*n*(n-1)/2-没有经过某种颜色的边的数量的求和 ...
- 【树形dp】hdu6035 Colorful Tree
非常棒的题解,我就不复述了:http://blog.csdn.net/Bahuia/article/details/76141574 O(n) #include<cstdio> #incl ...
- HDU-6035 Colorful Tree(树形DP) 2017多校第一场
题意:给出一棵树,树上的每个节点都有一个颜色,定义一种值为两点之间路径中不同颜色的个数,然后一棵树有n*(n-1)/2条 路径,求所有的路径的值加起来是多少. 思路:比赛的时候感觉是树形DP,但是脑袋 ...
- HDU6035:Colorful Tree(树形DP)
传送门 题意 给出一棵最小生成树及每个节点的颜色,询问\(\frac{n(n-1)}2\)条路径的权值和,一条路径的权值为该路径的颜色种数 分析 勉强理解了ftae的做法,但是代码还是不太会,还是太弱 ...
- 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 ...
- AtCoder Beginner Contest 133 F Colorful Tree
Colorful Tree 思路: 如果强制在线的化可以用树链剖分. 但这道题不强制在线,那么就可以将询问进行差分,最后dfs时再计算每个答案的修改值, 只要维护两个数组就可以了,分别表示根节点到当前 ...
- HDU 6035 - Colorful Tree | 2017 Multi-University Training Contest 1
/* HDU 6035 - Colorful Tree [ DFS,分块 ] 题意: n个节点的树,每个节点有一种颜色(1~n),一条路径的权值是这条路上不同的颜色的数量,问所有路径(n*(n-1)/ ...
- [HDU6793] Tokitsukaze and Colorful Tree
题目 又是一个条历新年,窗前的灼之花又盛开了. 时隔多年,现在只有这一棵树上盛开着残存的 \(n\) 朵灼之花了. 尽管如此,这些灼之 花仍散发出不同色彩的微弱的光芒. 灼之花的生命极为短暂,但它的花 ...
随机推荐
- Struts2漏洞利用
Struts漏洞合集 Struts-S2-013漏洞利用 受影响版本 Struts 2.0.0 - Struts 2.3.14.1 漏洞利用 任意命令执行POC: ${(#_memberAccess[ ...
- 【Linux常见问题】CentOS 7 root用户密码忘记,找回密码方法
1.开机按esc 2.选择CentOS Linux (3.10.0-693.......) 按 e 键: 3.光标移动到 linux 16 开头的行,找到 ro 改为 rw init=sysr ...
- 将不确定变成确定~LINQ DBML模型可以对应多个数据库吗
答案是肯定的,一个DBML模型可以对应多个数据库,只要数据库中的表与模型中定义的表结构完成相同,就可以这个技术,我们可以用来开发一些通用的功能模块,如通过后台管理模块,我们将一些通用表进行抽象,如,对 ...
- Mysql 查看被锁住的表
MYSQL 查看被锁住的表 -- 本文章仅用于学习,记录 当你在mysql 执行查询语句的时候,简单的一句查询语句却卡很久,一直转圈圈的时候,这时候你就需要怀疑数据库的哪些进程,哪些事物被锁住 ...
- 数学--数论--POJ 1061青蛙的约会 (扩展欧几里得算法)
青蛙的约会 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问 ...
- 网络流--最大流--HDU 3549 Flow Problem
题目链接 Problem Description Network flow is a well-known difficult problem for ACMers. Given a graph, y ...
- CentOS上安装比较习惯的代码编辑器
linux下的vim用起来不是很习惯,可能是能力有限.所以一直在找一种自己比较熟悉的代码编辑器,所以就找到了sublime text,安装方法网上有很多种,比较方便的方法:直接在csdn上下载一个破解 ...
- pycharm安装与破解
安装即教程地址: https://www.jianshu.com/p/355a6920116f 转载文章,资源失效可用这个链接下载: 链接:https://pan.baidu.com/s/1kBb3s ...
- springboot中json转换LocalDateTime失败的bug解决过程
环境:jdk1.8.maven.springboot 问题:前端通过json传了一个日期:date:2019-03-01(我限制不了前端开发给到后端的日期为固定格式,有些人就是这么不配合), ...
- Java种sleep和wait的区别
1,sleep方法是Thread类的静态方法,wait()是Object超类的成员方法 2,sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时 ...