题意:一棵有n个点的树,树上每个点都有颜色c[i],定义每条路径的值为这条路径上经过的不同颜色数量和。求所有路径的值的和。

可以把问题转化为对每种颜色有多少条不同的路径至少经过这种颜色的点,然后加和。求有多少条路径经过可以转换为总路径数-没有经过的路径数,只要求出没有经过的路径数就好了。

对于每一个相同颜色的点,它们将树割成一些个联通块,显然这些联通块内部之间的路径不会经过这种颜色。

于是问题转化为求点划分的联通块大小。

用类似于虚树的dfs办法,每次维护树上最左边的一段链,然后用栈进行数据的更新即可。

# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <bitset>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FDR(i,a,n) for(int i=a; i>=n; --i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
inline int Scan() {
int x=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-; ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-''; ch=getchar();}
return x*f;
}
inline void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
}
const int N=;
//Code begin... struct Edge{int p, next;}edge[N<<];
int head[N], cnt=;
int node[N], siz[N], num[N], tmp, sum[N], mark;
int st[N<<], f[N], col[N], pos;
LL ans=; void add_edge(int u, int v){edge[cnt].p=v; edge[cnt].next=head[u]; head[u]=cnt++;}
void dfs(int x, int fa){
siz[x]=;
for (int i=head[x]; i; i=edge[i].next) {
int v=edge[i].p;
if (v==fa) continue;
dfs(v,x); siz[x]+=siz[v];
}
}
void sol(int x, int fa){
num[x]=siz[x]; --sum[node[x]];
if (node[x]==node[fa]) --num[x];
if (col[node[x]]) tmp=st[col[node[x]]], --num[tmp];
if (fa) {
if (col[node[fa]]) tmp=st[col[node[fa]]], num[tmp]-=num[x];
f[++pos]=col[node[fa]]; col[node[fa]]=pos; st[pos]=x;
}
for (int i=head[x]; i; i=edge[i].next) {
int v=edge[i].p;
if (v==fa) continue;
sol(v,x);
}
if (fa) {
ans+=(LL)num[x]*(num[x]-)/; sum[node[fa]]-=num[x];
col[node[fa]]=f[col[node[fa]]];
}
}
void init(){
mem(head,); mem(siz,); mem(num,); mem(sum,); mem(col,); mem(f,);
ans=; mark=; cnt=; pos=;
}
int main ()
{
int cas=, n, u, v;
while (~scanf("%d",&n)) {
init();
FOR(i,,n) scanf("%d",node+i), sum[node[i]]=n;
FOR(i,,n) if (sum[i]) ++mark;
FOR(i,,n-) scanf("%d%d",&u,&v), add_edge(u,v), add_edge(v,u);
dfs(,);
sol(,);
FOR(i,,n) ans+=(LL)sum[i]*(sum[i]-)/;
ans=(LL)mark*n*(n-)/-ans;
printf("Case #%d: %lld\n",++cas,ans);
}
return ;
}

HDU 6035 Colorful Tree(dfs)的更多相关文章

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

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

  2. 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 ...

  3. 2017ACM暑期多校联合训练 - Team 1 1003 HDU 6035 Colorful Tree (dfs)

    题目链接 Problem Description There is a tree with n nodes, each of which has a type of color represented ...

  4. HDU 6035 Colorful Tree(补集思想+树形DP)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6035 [题目大意] 给出一颗树,一条路径的价值为其上点权的种类数,求路径总价值 [题解] 单独考虑 ...

  5. HDU 6035 Colorful Tree (树形DP)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6035 [题目大意] 给出一颗树,一条路径的价值为其上点权的种类数,求路径总价值 [题解] 我们计算 ...

  6. hdu 6035:Colorful Tree (2017 多校第一场 1003) 【树形dp】

    题目链接 单独考虑每一种颜色,答案就是对于每种颜色至少经过一次这种的路径条数之和.反过来思考只需要求有多少条路径没有经过这种颜色即可. 具体实现过程比较复杂,很神奇的一个树形dp,下面给出一个含较详细 ...

  7. hdu 6035 Colorful Tree(虚树)

    考虑到树上操作:首先题目要我们求每条路径上出现不同颜色的数量,并把所有加起来得到答案:我们知道俩俩点之间会形成一条路径,所以我们可以知道每个样例的总的路径的数目为:n*(n-1)/2: 这样单单的求, ...

  8. Hdu 5379 Mahjong tree (dfs + 组合数)

    题目链接: Hdu 5379 Mahjong tree 题目描述: 给出一个有n个节点的树,以节点1为根节点.问在满足兄弟节点连续 以及 子树包含节点连续 的条件下,有多少种编号方案给树上的n个点编号 ...

  9. 【hdu6035】 Colorful Tree dfs序

    题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题目大意:给你一棵树,树上每个节点都有一个颜色. 现在定义两点间的距离为两点最短路径上颜色集合 ...

随机推荐

  1. 20155327 嵌入式C语言课堂补交

    嵌入式C语言 题目要求 在作业本上完成附图作业,要认真看题目要求. 提交作业截图 作弊本学期成绩清零(有雷同的,不管是给别人传答案,还是找别人要答案都清零) 题目分析 分析一:提取插入时间 根据老师上 ...

  2. [2016北京集训试题8]连在一起的幻想乡[dp+无向图计数]

    Description Solution 本博客参考yww大佬的博客,为了加深理解我就自己再写一遍啦. 以下的“无向图”均无重边无自环. 定义f0[n]为n个点构成的无向图个数,f1[n]为n个点构成 ...

  3. Mac 安装PHP Redis 扩展

    其实 Mac 安装 Redis 还是很简单,以下为个人搭建配置.注意:文章中的“*”代表任意版本号 安装 Redis 服务 安装 brew install redis 使用 # 启动 redis-se ...

  4. 「Leetcode」13. Roman to Integer(Java)

    分析 把具体的情况一个一个实现即可,没有什么幺蛾子. 代码 class Solution { public int romanToInt(String s) { int ans = 0; for (i ...

  5. ShipStation Now Uses AWS And Amazon Fulfillment To Automatically Ship From eBay, Sears And Other Marketplaces

    ShipStation today unveiled a first-of-its-kind service to leverage Amazon Web Services and Amazon.co ...

  6. Javascript中Generator(生成器)

    阅读目录 Generator的使用: yield yield* next()方法 next()方法的参数 throw方法() return()方法: Generator中的this和他的原型 实际使用 ...

  7. Linux sync命令的作用分析

    Sync命令   在用reboot命令启动unix系统后,系统提示出错信息,部分应用程序不能正常工作.经仔细检查系统文件,并和初始的正确备份进行比较,发现某些文件确实被破坏了,翻来覆去找不到文件遭破坏 ...

  8. Python 招聘信息爬取及可视化

    自学python的大四狗发现校招招python的屈指可数,全是C++.Java.PHP,但看了下社招岗位还是有的.于是为了更加确定有多少可能找到工作,就用python写了个爬虫爬取招聘信息,数据处理, ...

  9. [python][odlboy]设置字符串打印的颜色

    格式:\033[显示方式;前景色;背景色m 说明:前景色            背景色           颜色---------------------------------------30    ...

  10. C++ STL 优先队列 priority_queue 详解(转)

    转自https://blog.csdn.net/c20182030/article/details/70757660,感谢大佬. 优先队列 引入 优先队列是一种特殊的队列,在学习堆排序的时候就有所了解 ...