A-啊啊啊啊啊_一起来做题~欢乐赛7 (nowcoder.com)

题目描述

样例

4
1 2
1 3
1 4
3

算法1

(换根dp)
分析:
  • 大体的思路就是先以某个节点为根计算出一个权值
  • 接着从这个节点开始移动
  • 计算每次从当前节点u移动到其子节点v对答案的影响
  • 影响就是减去以子节点v为根的子树所有节点经过边<u,v>的距离
  • 加上除v为根节点的子树外的所有节点经过边<u,v>的距离

状态转移:

状态表示:为以u为根的子树的权值

  1. 树形dp部分:

    解释:为以v为根的子树大小,每个节点经过边<u,v>都有一个贡献

  2. 换根dp部分:

    解释:- sz[v]先将以v为根的子树的影响消除,+ (n - sz[v]) 增加除以v为根的子树的节点外的点经过边<u,v>的贡献


细节:
每一条边的贡献不是单纯的1而是经过这条边的节点个数,可以说是子树大小

时间复杂度

参考文献

C++ 代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
// #include <unordered_map>
#include <vector>
#include <queue>
#include <set>
#include <bitset>
#include <cmath>
#include <map>

#define x first
#define y second

#define P 131

#define lc u << 1
#define rc u << 1 | 1

using namespace std;
typedef long long LL;
const int N = 1000010;
const LL INF = 0x3f3f3f3f3f3f3f3fll;
int h[N],ne[N * 2],e[N * 2],idx;
LL f[N];
int sz[N];
LL ans;
int n;

void add(int a,int b)
{
    e[idx] = b,ne[idx] = h[a],h[a] = idx ++;
}

void dfs1(int u,int father)
{
    sz[u] = 1;
    f[u] = 0;
    for(int i = h[u];~i;i = ne[i])
    {
        int j = e[i];
        if(j == father) continue;
        dfs1(j,u);
        f[u] += f[j] + sz[j];
        sz[u] += sz[j];
    }
}

void dfs2(int u,int father)
{
    for(int i = h[u];~i;i = ne[i])
    {
        int j = e[i];
        if(j == father) continue;
        f[j] = f[u] - sz[j] + (n - sz[j]);
        dfs2(j,u);
    }
    ans = min(ans,f[j]);
}

void solve()
{
    scanf("%d",&n);
    for(int i = 1;i <= n;i ++) h[i] = -1;
    for(int i = 0;i < n - 1;i ++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);
        add(b,a);
    }
    dfs1(1,0);
    ans = f[1];
    dfs2(1,0);
    printf("%lld\n",ans);
} 

int main()
{
    int _ = 1;

    // freopen("network.in","r",stdin);
    // freopen("network.out","w",stdout);
    // init(N - 1); 

    // std::ios_base::sync_with_stdio(0);
    // cin.tie(0);
    // cin >> _;

    // scanf("%d",&_);
    while(_ --)
    {
        // scanf("%lld%lld",&n,&m);
        solve();
        // test();
    }
    return 0;
}