hdu-6035 Colorful Tree
Posted Luke_Ye
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu-6035 Colorful Tree相关的知识,希望对你有一定的参考价值。
题目意思是计算所有路径(n*(n-1)/2)经过的不同颜色的数目和。
这个数目和可以转化为每种颜色经过的路径数目的求和,而这个求和又等价于颜色总数*n*(n-1)/2-没有经过某种颜色的边的数量的求和。
没有结果某种颜色的数量等价于由此颜色的节点将树拆分出多个联通块,每个联通块的节点数为k,则边数为k*(k-1)/2。
#include <iostream> #include <vector> #include <set> #define LL long long using namespace std; int n; const int N = 200050; vector<int> g[N]; LL sum[N];//维护以某种颜色为根的子树和 int colors[N]; bool vis[N]; LL wayCnt; void init() { fill(vis, vis + n + 1, 0); fill(sum, sum + n + 1, 0); for (int i = 0; i <= n; i++) g[i].clear(); wayCnt = 0; } LL dfs(int now) { int col = colors[now]; sum[col]++; LL preSum = sum[col];//用以计算当前点到某子树之间的联通块大小 vis[now] = 1; LL nowTreeSize = 1; int fuck = 0; for (int i = 0; i < g[now].size(); i++) { int nx = g[now][i]; if (vis[nx]) continue; LL siz=dfs(nx); LL change = sum[col] - preSum;//计算出底层增量 LL blockSize = siz - change; //cout << now << ": " << blockSize << endl; sum[col] += blockSize; preSum = sum[col]; fuck += blockSize; wayCnt += blockSize*(blockSize - 1) / 2; nowTreeSize += siz; } return nowTreeSize; } int main() { cin.sync_with_stdio(false); int cas = 1; while (cin >> n) { set<int> cc; for (int i = 1; i <= n; i++) cin >> colors[i],cc.insert(colors[i]); init(); for (int i = 0; i < n-1; i++) { int a, b; cin >> a >> b; g[a].push_back(b); g[b].push_back(a); } dfs(1); //cout << wayCnt << endl; for (int i = 1; i <=n; i++) { if (cc.find(i)!=cc.end()&&i != colors[1]) { LL blockSize = n - sum[i]; wayCnt += blockSize*(blockSize - 1) / 2; } } cout << "Case #" << cas++ << ": "; cout << cc.size()*n*(n-1)/2-wayCnt << endl; } return 0; }
以上是关于hdu-6035 Colorful Tree的主要内容,如果未能解决你的问题,请参考以下文章