ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

cf1060 E. Sergey and Subway(树形dp)

2022-01-15 03:00:35  阅读:190  来源: 互联网

标签:dfs int siz0 siz1 sum1 sum0 Sergey Subway cf1060


题意:

给定一棵树,然后在所有有相同邻点的点对之间连边。新连的边不能用于判断相邻。求所有点对的距离和。

思路:

法一:烦人的树形dp。维护子树中与根的距离为奇数的点数和距离为偶数的点数。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5 + 5, M = 4e5 + 5;
int h[N], e[M], ne[M], idx;
void add(int a, int b) {
    e[++idx] = b, ne[idx] = h[a], h[a] = idx;
}

ll res[N], siz1[N], siz0[N], sum1[N], sum0[N];
void dfs(int u, int fa)
{
    siz0[u] = 1;

    for(int i = h[u]; i; i = ne[i])
    {
        int v = e[i]; if(v == fa) continue;
        dfs(v, u);

        res[u] += sum0[u]/2 * siz1[v] + (sum1[v]+siz1[v])/2 * (siz0[u]-1)
        + (sum1[u]+siz1[u])/2 * siz0[v] + sum0[v]/2 * siz1[u]
        + (sum1[u]+siz1[u])/2 * siz1[v] + (sum1[v]+siz1[v])/2 * siz1[u]
        + sum0[u]/2 * siz0[v] + sum0[v]/2 * (siz0[u]-1) + siz0[v] * (siz0[u]-1);

        siz1[u] += siz0[v], siz0[u] += siz1[v];
        sum1[u] += siz0[v] + sum0[v], sum0[u] += siz1[v] + sum1[v];
    }
    res[u] += sum0[u]/2 + (sum1[u]+siz1[u])/2;
}

signed main()
{
    int n; scanf("%d", &n);
    for(int i = 1, a, b; i < n; i++) scanf("%d%d", &a, &b), add(a, b), add(b, a);

    dfs(1, 0);

    ll ans = 0;
    for(int i = 1; i <= n; i++) ans += res[i];
    printf("%lld", ans);

    return 0;
}

法二:不加边之前的答案为 \(\sum size_u(n-size_u)\) 。

加边后,距离为偶数的点对距离减半;奇数的减半后+1。

不加边前,ans=偶数层到偶数层的点对距离和(X)+奇数层到奇数层的点对距离和(Y)+奇数到偶数的点对距离和(Z) 。X和Y必然为偶数,缩小一半;Z的数量为深度为奇的点数×深度为偶的点数

ll siz[N], cnt;
void dfs(int u, int fa, int dep)
{
    siz[u] = 1;
    if(dep % 2) cnt++;
    for(int i = h[u]; i; i = ne[i]) {
        int v = e[i]; if(v == fa) continue;
        dfs(v, u, dep + 1);
        siz[u] += siz[v];
    }
}

ll ans = 0;
for(int i = 1; i <= n; i++) ans += siz[i] * (n - siz[i]);
ans += cnt * (n - cnt); ans /= 2;
printf("%lld", ans);

标签:dfs,int,siz0,siz1,sum1,sum0,Sergey,Subway,cf1060
来源: https://www.cnblogs.com/wushansinger/p/15806036.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有