zoukankan      html  css  js  c++  java
  • gym/102253C Colorful Tree 树上计数

    题意:有一颗数,每个点有一个颜色,定义两点之间的距离为两点路径之间不同颜色的数目,问所有路径的距离和是多少?

    思路:每个颜色的贡献为路径中有这个颜色的路径数。先假设所有路径都会经过一种颜色,再减去不会经过这个颜色的路径数就是这个颜色的贡献。

    看一下这个博客会好理解一些吧:https://blog.csdn.net/f_zyj/article/details/76168180

    代码:

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int maxn = 200010;
    vector<int> G[maxn];
    int c[maxn];
    LL ans[maxn * 2], res;
    int s[maxn];
    int n;
    void add(int x, int y) {
    	G[x].push_back(y);
    	G[y].push_back(x);
    }
    LL dfs(int x, int fa) {
    	LL sz = 1, tmp = s[c[x]];
    	s[c[x]] = x;
    	for (int i = 0; i < G[x].size(); i++) {
    		int y = G[x][i];
    		if(y == fa) continue;
    		ans[x] = 0;
    		LL sz1 = dfs(y, x);
    		res -= (LL)(sz1 - ans[x]) * (sz1 - ans[x] - 1) / 2;
    		sz += sz1;
    	}
    	if(tmp <= n) ans[tmp] += sz;
    	else ans[tmp] -= sz;
    	s[c[x]] = tmp;
    	return sz;
    }
    set<int> st;
    set<int>::iterator it;
    int main() {
    	int x, y, kase = 0;
    	while(~scanf("%d", &n)) {
    		st.clear();
    		res = 0;
    		for (int i = 1; i <= n; i++) {
    			scanf("%d", &c[i]);
    			G[i].clear();
    			s[i] = 0;
    			st.insert(c[i]);
    			ans[i] = 0;
    		}
    		for (it = st.begin(); it != st.end(); it++) {
    			ans[(*it) + n] = n;
    			s[(*it)] = (n + (*it));
    		}
    		for (int i = 1; i < n; i++) {
    			scanf("%d%d", &x, &y);
    			add(x, y);
    		}
    		res = (LL) st.size() * n * (n - 1) / 2;
    		dfs(1, -1);
    		for (it = st.begin(); it != st.end(); it++) {
    			res -= ans[(*it) + n] * (ans[(*it) + n] - 1) / 2;
    		}
    		printf("Case #%d: %lld
    ", ++kase, res);
    	}
    }
    

      

  • 相关阅读:
    Linux系统_Linux平台“盖茨木马”初步了解
    查杀病毒的NB命令
    rabbitmq 常用的一些命令
    date 修改系统时间
    mkpasswd
    关于haproxy负载均衡的算法整理
    MySQL数据表中内容大小写区分的设置
    查看某个端口的连接数
    rabbitmq
    mysqldump 报导常
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/11129855.html
Copyright © 2011-2022 走看看