题意:一棵有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. 关于Linux_shell中的管道命令pipe “|”的简单学习和使用

    什么是 "|"? |其实是linux shell 中的一个命令:管道命令(pipe) 管道命令操作符是:"|",它仅能处理经由前面一个指令传出的正确输出信息,也 ...

  2. html 第一行不缩进,第二行缩进,文字对齐

    <p style="text-indent: -7rem;margin-left: 7rem;"> <img src="images/记录要求.png& ...

  3. springboot 中根据数据库表生成所有表的model,mapper和xml文件

    参考文件:https://blog.csdn.net/shenmoren6/article/details/80337662?utm_source=blogxgwz1 详细信息:https://blo ...

  4. ABP中module-zero快速集成微信用户认证

     https://personball.com/abp/2019/01/01/introduce-abp-module-zero-external-authenticate 

  5. git remote add origin错误

    如果输入$ Git remote add origin git@github.com:djqiang(github帐号名)/gitdemo(项目名).git 提示出错信息:fatal: remote ...

  6. MySQL-MMM方案

    参考文档: 官方文档:http://mysql-mmm.org/mmm2:guide 本文对mmm方案做简单介绍,并做1个简单的验证. 一.MySQL-MMM方案 1. MMM方案简介 MMM(Mul ...

  7. Jenkins 自动化测试

    学习 Jenkins 自动化测试的系列文章 Robot Framework 概念 Robot Framework 安装 Pycharm + Robot Framework 环境搭建 Robot Fra ...

  8. [笔记] postgresql 流复制(streaming replication)

    基本环境说明: os:FreeBSD 9.3 postgresql version: master:192.168.56.101 standby:192.168.56.102 安装过程略,基于pkg包 ...

  9. loadrunner socket协议问题归纳(5)

    获取服务器的返回值,可以用web_reg_save_param函数,该参数最好放到: 语法: int web_reg_save_param(const char *ParamName, <lis ...

  10. Linux学习—导航文件系统

    与windows相同,Linux操作系统也是以被称之为分层目录结构的方式来组织文件的.这意味着文件是以树形结构的目录中进行组织的,该树形结构目录可能包含文件和其他目录.文件系统的第一个目录叫做根目录, ...