题意:一棵有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. echarts x轴文字换行显示

    xAxis : [ { splitLine:{show:false}, type : 'category', data : ['社交人际','沟通交流','心理认知','游戏玩耍','大小运动','生 ...

  2. pytest使用笔记(三)——pytest+allure+jenkins配置使用

    按照pytest使用笔记(二)把pytest+allure配置好后,现在在jenkins配置好,先实现手动构建(立个小目标) 一,安装jenkins插件 首页->系统管理->插件管理,从“ ...

  3. 英特尔® 实感™ 前置摄像头 SR300 和 F200 的比较

    原文地址 简介 SR300 是支持 Microsoft Windows 10 操作系统的第二代英特尔® 实感™ 前置摄像头. 与 F200 摄像头型号相似,SR300 使用编码光深技术,在更小范围内创 ...

  4. cmake-cmake.1-3.11.4机翻

    指数 下一个 | 上一个 | CMake » git的阶段 git的主 最新发布的 3.13 3.12 3.11.4 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 ...

  5. ObjectAnimator实现菜单的弹出(扇形)

    用ObjectAnimator 实现菜单的弹出 首先是菜单的图片资源和布局 布局中使用FrameLaout 将菜单唤出对应的imageView放在布局的最后面来隐藏菜单详细内容. <?xml v ...

  6. 【C#】人脸识别 视频数据转图片数据

    使用虹软人脸识别的开发过程中遇到了转换的问题 因为不会用C#直接打开摄像头,就只能用第三方dll.一开始用Aforge,后来发现有个问题,关闭摄像头老是陷入等待,所以抛弃了.前一阵子开始用封装了Ope ...

  7. win10 tomcat不能访问问题

    问题描述:电脑是Win10系统的,安装了Tomcat后,本机通过80端口能顺利访问.但局域网内的其他机器却无法访问这台电脑的Tomcat服务. 故障分析: 将防火墙关闭后,可以访问,所以问题就出在防火 ...

  8. 爬虫:Scrapy12 - Stats Collection

    Scrapy 提供了方便的收集数据的机制.数据以 key/value 方式存储,值大多是计数值.该机制叫做数据收集器(Stats Collector),可以通过 Crawler API 的属性 sta ...

  9. 关于JavaScript定时器我的一些小理解

    因为自己在平时工作中,有些功能需要用到定时器,但是定时器并不像我们表边上看到的那样,所以这周末我看看书查查资料,深入研究了一下JavaScript中的定时器,那么废话不多说,下面进入我们今天的正题. ...

  10. Sorting a Three-Valued Sequence(三值排序)

    Description 排序是一种很频繁的计算任务.现在考虑最多只有三值的排序问题.一个实际的例子是,当我们给某项竞赛的优胜者按金银铜牌序的时候. 在这个任务中可能的值只有三种1,2和3.我们用交换的 ...