博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU-6035 Colorful Tree(树型dp)
阅读量:3758 次
发布时间:2019-05-22

本文共 3144 字,大约阅读时间需要 10 分钟。

Colorful Tree

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 512    Accepted Submission(s): 189
Problem Description
There is a tree with
n nodes, each of which has a type of color represented by an integer, where the color of node
i is
ci .
The path between each two different nodes is unique, of which we define the value as the number of different colors appearing in it.
Calculate the sum of values of all paths on the tree that has
n(n1)2 paths in total.
 
Input
The input contains multiple test cases.
For each test case, the first line contains one positive integers
n , indicating the number of node.
(2n200000)
Next line contains
n integers where the
i -th integer represents
ci , the color of node
i .
(1cin)
Each of the next
n1 lines contains two positive integers
x,y
(1x,yn,xy) , meaning an edge between node
x and node
y .
It is guaranteed that these edges form a tree.
 
Output
For each test case, output "
Case # x : y " in one line (without quotes), where
x indicates the case number starting from
1 and
y denotes the answer of corresponding case.
 
Sample Input
31 2 11 22 361 2 1 3 2 11 21 32 42 53 6
 
Sample Output
Case #1: 6Case #2: 29

题目要求每条路径经过的不同颜色数之和,可以转换成每种颜色对答案的贡献

“有多少条路径经过一个或多个颜色x的点”可以转换成“有多少条路径不经过颜色x”
即:经过颜色x的路径数量=n(n-1)/2-不经过颜色x的路径数
怎么求不经过颜色x的路径数呢?
我们可以想象把颜色为x的点选出来,这些点会把树分成若干个子树,这些子树内的路径都是不会经过颜色为x的点的
这样我们通过dfs遍历到顶点u,颜色为x,在它的子树内所有以颜色x为根的子树都要舍去
这一做法很简单:维护一个sum[i]表示以颜色i为根的子树总大小,每次遍历u的子节点v时,sum[col[u]]就会增加,
其增加量tmp就是子树v中以颜色col[u]为根的子树大小,用sz[v]-tmp就是子树v中颜色部位col[u]的点

#include
using namespace std;typedef long long LL;const int MX = 2e5 + 5;const LL mod = 1e9 + 7;struct Edge { int v, nxt;} E[MX * 2];int head[MX], rear;void add(int u, int v) { E[rear].v = v; E[rear].nxt = head[u]; head[u] = rear++;}int col[MX];int sz[MX];int vis[MX];LL sum[MX];LL ans;void init(int n) { for (int i = 1; i <= n; i++) head[i] = -1, vis[i] = sum[i] = 0; rear = 0;}void dfs(int u, int fa) { sz[u] = 1; LL pre = sum[col[u]], c = 0, szv; for (int i = head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if (v == fa) continue; dfs(v, u); sz[u] += sz[v]; LL tmp = sum[col[u]] - pre;//子树v中以颜色col[u]为根的子树大小 szv = sz[v] - tmp; //子树v中其它颜色的连通的节点数量 pre = sum[col[u]]; ans -= szv * (szv - 1) / 2; c += tmp; //c为了避免重复计算sz[u]的大小 } sum[col[u]] += sz[u] - c; //sum[col[u]]加上以u为根的子树大小}int main() { int n, cas = 0; //freopen("in.txt", "r", stdin); while (~scanf("%d", &n)) { init(n); int cnt = 0; for (int i = 1; i <= n; i++) { scanf("%d", &col[i]); if (!vis[col[i]]) { vis[col[i]] = 1; cnt++; } } for (int i = 1, u, v; i < n; i++) { scanf("%d%d", &u, &v); add(u, v); add(v, u); } ans = (LL)cnt * n * (n - 1) / 2; dfs(1, -1); for (int i = 1; i <= n; i++) { if (sum[i] == 0) continue; LL tmp = n - sum[i]; ans -= tmp * (tmp - 1) / 2; } printf("Case #%d: %lld\n", ++cas, ans); } return 0;}

转载地址:http://mswpn.baihongyu.com/

你可能感兴趣的文章
利用php对数据库进行操作
查看>>
二叉树及其(前中后)序遍历
查看>>
2020.8.29 ssdh
查看>>
PyCharm使用技巧及常用快捷键
查看>>
ubuntu内存爆满卡住,一顿操作任务栏菜单栏消失再解决办法记录
查看>>
ubuntu下pycharm无法输入中文解决办法(记录)
查看>>
torch.cuda.is_available()返回False的解决办法
查看>>
BITVehicle_Dataset数据集转换
查看>>
将视频转存成图片小代码
查看>>
ImportError: cannot import name ‘Line 解决方法
查看>>
Ubuntu 创建/删除虚拟环境
查看>>
deepsort算法中绘制轨迹部分的代码【记录】
查看>>
C++程序设计作业--坦克大战[分享]
查看>>
Uuntu20.04出现“qt.qpa.plugin: Could not load the Qt platform plugin “xcb“ in...已放弃 (核心已转储)”问题解决记录
查看>>
Linux系统常用的基本操作记录
查看>>
ZeroDivisionError: integer division or modulo by zero解决记录
查看>>
使用软链接放置数据集
查看>>
wx-charts折线统计图的实现(以每日体重展示为例)
查看>>
Windows消息:如何自定义窗口消息与线程消息
查看>>
Windows消息:怎样使用RegisterWindowMessage注册消息
查看>>