(2017多校训练第一场)HDU - 6035 Colorful Tree 树形dp

这道题目我只能勉强看懂,题解就不写了,下面的博客写的很好。

hdu 6035 树形dp

代码如下:

#include 

using namespace std;

typedef long long int LL;
const LL MAX_N = 200005;
vector G[MAX_N];
LL col[MAX_N];
LL vis[MAX_N];
LL siz[MAX_N];
LL sum[MAX_N];
LL ans;

void dfs(LL u, LL fa)
{
    siz[u] = 1;
    LL all = 0;
    for (unsigned i = 0; i < G[u].size(); i++)
    {
        LL v = G[u][i];
        if (v == fa)
            continue;
        LL pre = sum[col[u]];
        dfs(v, u);
        LL add = sum[col[u]] - pre;
        LL tmp = siz[v] - add;
        ans -= tmp * (tmp - 1) / 2;
        all += add;
        siz[u] += siz[v];
    }
    sum[col[u]] += siz[u] - all;
}

int main()
{
    //freopen("test.txt", "r", stdin);
    cin.sync_with_stdio(false);
    LL n;
    LL Case = 1;
    while (cin >> n)
    {
        memset(col, 0, sizeof(col));
        memset(vis, 0, sizeof(vis));
        memset(siz, 0, sizeof(siz));
        memset(sum, 0, sizeof(sum));
        LL cnt = 0;
        for (LL i = 1; i <= n; i++)
        {
            cin >> col[i];
            if (!vis[col[i]])
            {
                cnt++;
                vis[col[i]] = 1;
            }
            G[i].clear();
        }
        for (LL i = 1; i < n; i++)
        {
            LL u, v;
            cin >> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        ans = cnt * n * (n - 1) / 2;
        dfs(1, 0);
        for (LL i = 1; i <= n; i++)
        {
            if (!vis[i])
                continue;
            ans -= (n - sum[i]) * (n - sum[i] - 1) / 2;
        }
        cout << "Case #" << Case++ << ": " << ans << endl;
    }
    return 0;
}


你可能感兴趣的:(ACM-树形dp)