HDU 6035 Colorful Tree

Problem : 给一棵树,每个结点有一种颜色,定义每条路径的权值为这条路径上颜色的种数,询问所有路径(C(n,2)条)的权值之和。

Solution : 分开考虑每种颜色对答案的贡献。对于一种颜色,一共有C(n,2)条路径,再考虑问题的反面。不含有这种颜色的路径的数量,即为将这棵树上所有这种颜色的点删去后,所有剩下的树的路径数量。

问题关键在于统计删去点之后每颗树的大小,对于每个节点要计算删去其所有相同颜色的子树,用栈进行维护。即每次访问到每个节点时,将其最近的相同颜色的祖先的大小减去该子树的大小。

#include <bits/stdc++.h>

using namespace std;

const int N = 200008;

vector <int> eg[N];

int cl[N];
int flag[N];
int size[N];
int nt[N], st[N];
long long tag[N];
long long tagrt[N]; int n; void dfs(int u, int fa)
{
size[u] = 1;
for (auto v : eg[u])
{
if (v == fa) continue;
dfs(v, u);
size[u] += size[v];
}
}
void solve(int u, int fa)
{
int rt;
int last = st[cl[u]];
if (last == 0)
{
rt = 1;
tagrt[cl[u]] += size[u];
}
else
{
rt = nt[last];
tag[rt] += size[u];
}
st[cl[u]] = u;
for (auto v: eg[u])
{
if (v == fa) continue;
nt[u] = v;
solve(v, u);
}
st[cl[u]] = last;
} int main()
{
cin.sync_with_stdio(0);
int cas = 0;
while (cin >> n)
{
for (int i = 1; i <= n; ++i)
{
size[i] = nt[i] = tag[i] = tagrt[i] = flag[i] = 0, eg[i].clear();
}
for (int i = 1; i <= n; ++i) cin >> cl[i], flag[cl[i]] = 1;
int num = 0;
for (int i = 1; i <= n; ++i) num += flag[i];
long long ans = 1ll * n * (n - 1) / 2 * num;
for (int i = 1; i < n; ++i)
{
int u, v;
cin >> u >> v;
eg[u].push_back(v);
eg[v].push_back(u);
}
dfs(1, 0);
solve(1, 0); for (int i = 2; i <= n; ++i)
{
int p = size[i] - tag[i];
ans -= 1ll * p * (p - 1) / 2;
}
for (int i = 1; i <= n; ++i)
if (flag[i])
{
int p = size[1] - tagrt[i];
ans -= 1ll * p * (p - 1) / 2;
}
cout << "Case #" << ++cas << ": " << ans << endl;
}
}

HDU 6035 (虚树)(统计颜色)的更多相关文章

  1. HDU 6070 (线段树)(统计颜色)

    HDU 6070 Partition Problem : 给一段长度为n的序列,要求找出一段区间,使得这段区间的数字种类除以区间长度最小.输出最后的答案即可.(n <= 60000)(9s时限) ...

  2. BZOJ 3879: SvT 虚树 + 后缀自动机

    Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始 ...

  3. CF1073G Yet Another LCP Problem 后缀自动机 + 虚树 + 树形DP

    题目描述 记 $lcp(i,j)$ 表示 $i$ 表示 $i$ 这个后缀和 $j$ 这个后缀的最长公共后缀长度给定一个字符串,每次询问的时候给出两个正整数集合 $A$ 和 $B$,求$\sum_{i\ ...

  4. hdu 6035 Colorful Tree(虚树)

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

  5. HDU 6430 Problem E. TeaTree(虚树)

    Problem E. TeaTree Problem Description Recently, TeaTree acquire new knoledge gcd (Greatest Common D ...

  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. [PKUWC2019]Day1 T2 你和虚树的故事

    选择k个颜色,使得颜色的虚树有交的方案数 肯定要考虑连通块的贡献. 法一 https://www.cnblogs.com/xzz_233/p/10292983.html 枚举连通块还是不可行的. 枚举 ...

  9. 51Nod1868 彩色树 虚树

    原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1868.html 题目传送门 - 51Nod1868 题意 给定一颗 $n$个点的树,每个点一个 $[ ...

随机推荐

  1. android xml中使用include标签

    在一个项目中,我们可能会在xml中局部用到相同的布局,如果每次都在xml中重写这些布局,代码显得很冗余.重复的复制黏贴也很烦恼,所以,我们把这些相同的局部布局写成一个单独的xml模块,需要用到这些布局 ...

  2. 算法之A星算法(寻路)

    1.启发式搜索:启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标.这样可以省略大量无谓的搜索路径,提高了效率.在启发式搜索中,对位置的估价是十分 ...

  3. Linux php安装zip扩展

    Linux php安装zip扩展 2018.07.22 22:40 1165浏览   #wget http://pecl.php.net/get/zip-1.12.4.tgz #tar zxfv zi ...

  4. expand - 把 tab 符转换为空格符

    总览 (SYNOPSIS) ../src/expand [OPTION]... [FILE]... 描述 (DESCRIPTION) 把 各文件 FILE 中的 tab 符 转换为 空格符, 然后 写 ...

  5. C++内联函数的使用

    1.为什么要用内联函数? 在C++中我们通常定义以下函数来求两个整数的最大值: int max(int a, int b) { return a > b ? a : b; } 为这么一个小的操作 ...

  6. Qt _六天的学习路线

    六天的学习路线:第一天:    1.Qt的介绍    2.Qt的框架    3.项目文件(.pro)    4.第一个Qt程序(hello Qt)    5.父窗口和子窗口的区别(控件,部件,构件)  ...

  7. 让idea调试不进入class文件中去

  8. iOS之绘制像素到屏幕

    译注:这篇文章虽然比较长,但是里面的内容还是很有价值的. 像素是如何绘制到屏幕上面的?把数据输出到屏幕的方法有很多,通过调用很多不同的framework和不同的函数.这里我们讲一下这个过程背后的东西. ...

  9. luogu P2078 朋友

    题目背景 小明在A公司工作,小红在B公司工作. 题目描述 这两个公司的员工有一个特点:一个公司的员工都是同性. A公司有N名员工,其中有P对朋友关系.B公司有M名员工,其中有Q对朋友关系.朋友的朋友一 ...

  10. SG定理与SG函数

    一个蒟蒻来口胡$SG$函数与$SG$定理. 要是发现有不对之处望指教. 首先我们来了解一下$Nim$游戏. $Nim$游戏是公平组合游戏的一种,意思是当前可行操作仅依赖于当前局势. 而经典$Nim$游 ...