zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    opencv掩模操作
    cvtColor()学习
    opencv中mat类介绍
    c++中的stl
    opencv3中SurfFeatureDetector、SurfDescriptorExtractor、BruteForceMatcher的使用
    CUDA学习
    visual studio + opencv + contrib
    11.14/11.15 Apache和PHP结合 11.16/11.17 Apache默认虚拟主机
    11.10/11.11/11.12 安装PHP5 11.13 安装PHP7
    11.6 MariaDB安装 11.7/11.8/11.9 Apache安装
  • 原文地址:https://www.cnblogs.com/LukeStepByStep/p/7270676.html
Copyright © 2011-2022 走看看