题意:给出一棵树,树上的每个节点都有一个颜色,定义一种值为两点之间路径中不同颜色的个数,然后一棵树有n*(n-1)/2条

路径,求所有的路径的值加起来是多少。

思路:比赛的时候感觉是树形DP,但是脑袋抽了,忘记树形DP是怎么遍历的了(其实没忘也不会做:)

先给出官方题解吧:

单独考虑每一种颜色,答案就是对于每种颜色至少经过一次这种的路径条数之和。反过来思考只需要求有多少条路径没有经过这种颜色即可。直接做可以采用虚树的思想(不用真正建出来),对每种颜色的点按照 dfs 序列排个序,就能求出这些点把原来的树划分成的块的大小。这个过程实际上可以直接一次 dfs 求出。

其实感觉就前面那两句能看懂= =,不过这个也才是主要的。很显然这题是算每个节点的贡献,但是每个节点都算的话就会算重,去重不容易,所以就可以计算

有哪些路径没有经过这种颜色,这个就很容易一点了,所以对于每种颜色就是求他的联通快的大小。

然后感觉还是不容易,可能是树形DP做少了吧,通过这个题还是学到不少的技巧 比如通过访问节点前,把前面的颜色给存起来,这样到时候访问的就是这颗子树的内容了,更新这些内容的时候一定要注意他们之间的关系

/** @xigua */
#include<stdio.h>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
#include<queue>
#include<set>
#include<string>
#include<map>
#define PI acos(-1)
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 2e5 + 5;
const ll maxm = 1e7;
const int mod = 1e9 + 7 + 0.1;
const int INF = 1e9 + 7;
const ll inf = 1e15 + 5;
const db eps = 1e-9;
const int state = 15;
ll ans, col[maxn];
int head[maxn], cnt, n, siz[maxn], vis[maxn], c[maxn];
struct Edge {
int v, next;
} e[maxn<<1]; void add(int u, int v) {
e[cnt].v = v;
e[cnt].next = head[u];
head[u] = cnt++;
} void init() {
cnt = ans = 0;
memset(head, -1, sizeof(head));
memset(vis, 0, sizeof(vis));
memset(col, 0, sizeof(col));
} void dfs(int u, int fa) {
siz[u] = 1;
vis[c[u]] = 1;
int pre = col[c[u]]; //访问节点前的
int num = 0; //因为一个节点有好几个儿子,所以就要把前面的给剔除
for (int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
if (fa == v) continue;
dfs(v, u);
siz[u] += siz[v];
ll tmp = siz[v] - (col[c[u]] - pre - num);
ans -= (tmp - 1) * tmp / 2;
num = col[c[u]] - pre; //num就是当前颜色的个数减去以前的就是节点u的前面的儿子的
}
col[c[u]] = pre + siz[u];
} void solve() {
int cas = 1; while (cin >> n) {
init();
for (int i = 1; i <= n; i++)
scanf("%d", c + i);
for (int i = 1; i < n; i++) {
int u, v; scanf("%d%d", &u, &v);
add(u, v); add(v, u);
}
dfs(1, -1);
for (int i = 1; i <= n; i++) {
if (vis[i]) {
ans += (ll)n * (n - 1) / 2;
ll tmp = n - col[i];
ans -= tmp * (tmp - 1) / 2;
}
}
printf("Case #%d: %I64d\n", cas++, ans);
}
} int main() {
int t = 1, cas = 1;
//freopen("in.txt", "r", stdin);
// scanf("%d", &t);
// init();
while(t--) {
// printf("Case #%d:\n", cas++);
solve();
}
return 0;
}

  

HDU-6035 Colorful Tree(树形DP) 2017多校第一场的更多相关文章

  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. hdu 6035:Colorful Tree (2017 多校第一场 1003) 【树形dp】

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

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

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

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

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

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

  7. HDU 6035 Colorful Tree (树形DP)

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

  8. HDU 6035 Colorful Tree(dfs)

    题意:一棵有n个点的树,树上每个点都有颜色c[i],定义每条路径的值为这条路径上经过的不同颜色数量和.求所有路径的值的和. 可以把问题转化为对每种颜色有多少条不同的路径至少经过这种颜色的点,然后加和. ...

  9. hdu 6035 Colorful Tree(虚树)

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

随机推荐

  1. Lightoj 1094 【DFS】

    题意: 给你一颗n-1条边的树,求某两点的最长路 思路: 随便找个根,然后我们从根往下搜,对于每个结点会出现多个子节点或者一个子节点或者没有结点, 多个子节点的话,就以他为中间点,在子节点中找两条最长 ...

  2. 微信小程序取消button边框线

    先给button定义个class属性 <button class="an"> 按钮 </button> 然后再css上加上 .an::after { bor ...

  3. 51nod1625(枚举&贪心)

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1625 题意:中文题诶- 思路:枚举+贪心 一开始写的行和列同时 ...

  4. IT兄弟连 JavaWeb教程 JSP与Servlet的联系

    Servlet是使用Java Servlet接口(API)运行在Web服务器上的Java程序,其功能十分强大,它不但可以处理HTTP请求中的业务逻辑,而且还可以输出HTML代码来显示指定页面,而JSP ...

  5. SpringBoot2.0 整合 QuartJob ,实现定时器实时管理

    一.QuartJob简介 1.一句话描述 Quartz是一个完全由java编写的开源作业调度框架,形式简易,功能强大. 2.核心API (1).Scheduler 代表一个 Quartz 的独立运行容 ...

  6. dream(2018.10.17)

    一句话题意:讲什么题意啊,见usaco2017feb silver的T1,一模一样,就是牛和鸡的读入顺序反过来了一下,数据范围大了10倍,卡掉了\(O(n^2)\)的算法. 数据范围: 对于 30%的 ...

  7. web.xml中一个filter配置多个url-pattern

    需要在filter标签后添加多个filter-mapping标签,一个url-pattern就对应一个filter-mapping标签,不能直接把多个url-pattern配置到同一个filter-m ...

  8. [題解/狀壓dp]POJ_2411_Mondriaan's dream

    关于“我读过很多书,到后来大部分都被我忘记了,那阅读的意义是什么?”的疑问,我看过最巧妙的一个回答:当我还是个孩子的时候,我吃过很多的食物,大部分已经一去不复返而且被我忘记了,但可以肯定的是,它们中的 ...

  9. DRF教程2-请求和响应

    Request objects REST framework中有一个Request对象,是HttpRequest的扩展,提供了新的请求解析,Request的核心功能就是request.data,它和r ...

  10. UWP 切换语言

    关于UWP切换语言的具体可以看这篇.http://www.cnblogs.com/hupo376787/p/7775291.html 这里我就记录一些自己的. 目前大多数软件用的都是利用文本资源文件来 ...