【树形DP】ZOJ - 3949 Edge to the Root

翻译 2018年04月17日 10:38:51

Step1 Problem:

给出一颗根为 1 的树,每条边边长为 1,请你从根连一条边到某个点,使得根到各点距离的总和最小,求这个最小距离。
数据范围:
1<=n<=2e5

Step2 Involving:

树形DP

Step3 Ideas:

假设 1 到 x 连边,受影响的只有 1 和 x 中点往下的点。
例如:一条链长度为 n,给它们按顺序 1 到 n 编号,1 和 n 连边,受影响的只有 (1+n)/2+1 点和往下的点,我们称 (1+n)/2+1 为 1 到 n 的中点
我们需要求 1 和其他所有点连边的 距离和变化值,然后求变化值最大。
假设 u 是 f 的孩子。
我们从 1 和 u 连边,变化到 1 和 f 连边
f 子树所有结点 距离都减少了 1
1 到 f 的中点子树所有结点 距离都增加了1( f 子树所有结点除外)
那么我们只要预处理出,每个子树的孩子数 siz[]。
1 和 u 连边变化量为 now
1 和 f 连边变化量为 now - siz[st[cnt]] + (siz[st[(cnt+1)/2 + 1]] - siz[st[cnt]]);// st[i] 是 i 编号对应的那个结点

Step4 Code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5+100;
const int inf = 0x3f3f3f3f;
vector<int> Map[N];
int head[N], cnt;
int siz[N], dep[N], st[N];
ll ans;
void dfs1(int u, int f)//预处理出子树孩子数(包括自身),求出最大距离
{
    siz[u] = 1; dep[u] = dep[f] + 1;
    ans += dep[u];
    for(int i = 0; i < Map[u].size(); i++)
    {
        int to = Map[u][i];
        if(to != f)
        {
            dfs1(to, u);
            siz[u] += siz[to];
        }
    }
}
ll Min;
void dfs2(int u, int f, ll now)//求出最大变化量
{
    st[++cnt] = u;
    ll now1 = now;
    if(cnt > 2)
    {
        now1 = now - siz[st[cnt]] + (siz[st[(cnt+1)/2 + 1]] - siz[st[cnt]]);
        Min = min(Min, now1);
    }
    for(int i = 0; i < Map[u].size(); i++)
    {
        int to = Map[u][i];
        if(to != f)
        {
            dfs2(to, u, now1);
            cnt--;
        }
    }
}
int main()
{
    int T, n, u, v;
    cin >> T;
    while(T--)
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) Map[i].clear();
        memset(head, -1, sizeof(head));
        cnt = 0;
        for(int i = 1; i < n; i++)
        {
            scanf("%d %d", &u, &v);
            Map[u].push_back(v);
            Map[v].push_back(u);
        }
        dep[0] = -1; cnt = ans = Min = 0;
        dfs1(1, 0);
        dfs2(1, 0, 0);
        cout << ans+Min << endl;
    }
    return 0;
}

ZOJ 3949 (树形DP)

Edge to the Root Time Limit: 1000MS   Memory Limit: 131072KB   64bit IO Format: %lld & ...
  • know_heng
  • know_heng
  • 2017-04-25 15:20:14
  • 280

ZOJ - 3949 Edge to the Root

Edge to the Root题意是给出一个棵树,每条边权都为1,要求在点1和点x之间连一条边,使得连边之后,点1到所有点的路径长度之和最小。 输出最小长度之和。 显然对于一棵树,添一条边之后,...
  • qq_34317623
  • qq_34317623
  • 2017-04-16 20:52:44
  • 607

zoj 3949 Edge to the Root 2017浙大校赛B

Given a tree with n vertices, we want to add an edge between vertex 1 and vertex x, so that the sum ...
  • lqybzx
  • lqybzx
  • 2017-04-13 20:53:31
  • 729

【ZOJ3949 The 17th Zhejiang University Programming Contest B】【树形DP】Edge to the Root 树上加一边 根距离之和尽可能小

Edge to the Root Time Limit: 1 Second      Memory Limit: 131072 KB Given a tree with n vertice...
  • snowy_smile
  • snowy_smile
  • 2017-04-12 17:03:58
  • 753

Edge to the Root ZOJ - 3949 (树形DP)

Given a tree with n vertices, we want to add an edge between vertex 1 and vertex x, so that the sum ...
  • wangshuhe963
  • wangshuhe963
  • 2018-04-10 19:57:28
  • 7

ZOJ 3949 Edge to the Root(树形DP)

题意给定一棵树,选一个节点和根相连,使得最后所有点到根的距离和最小,求最小距离和思路首先一个点和根连起来以后,影响的只有根到这个点这条路径上的点,以及他们的子树,并且对于每个点影响的权值都是能够确定的...
  • Martin20150405
  • Martin20150405
  • 2017-04-18 10:36:23
  • 432

ZOJ - 3949 Edge to the Root——树形dp

首先用dp1【i】维护一下【以节点i为根节点的子树】的节点数(包括i)然后从根节点向下递推,用dp2【i】表示在根节点和i节点之间连边以后的距离之和,那么我们从节点u推到他的子节点v时,距离之和首先要...
  • hao_zong_yin
  • hao_zong_yin
  • 2018-04-13 09:11:03
  • 24

ZOJ3734 树形DP

很有意思的一道树形DP。关键在于变量的设置。根据翻转的性质,我们设dp[ i ][ 0 ]代表以 i 为根的子树like 比 candle多多少,dp[ i ][ 1 ]则表示以 i 为根的子树lik...
  • u010523907
  • u010523907
  • 2014-03-01 16:00:37
  • 935

ZOJ 3949 树形DP

题意给一棵树加一条边,使得根到所有点的距离之和最小,问最小的距离之和是多少。题解一道很考思维的树形DP。首先的话,先用简单DFS求出每个点的子节点数量和以及总路径长度。然后再尝试加边,计算加边以后能减...
  • zhenlingcn
  • zhenlingcn
  • 2017-08-12 08:38:24
  • 139

ZOJ - 3949(树形dp)

题解:我们先求出所有根到所有树上路径的总值,最后我们需要求的是加到哪条边上面的值后权值最小,假设根是第0层,u是第n层,求第i层会开始变少那么,数值应该是 n-i+1-i&amp;lt;0  =》 (...
  • a1325136367
  • a1325136367
  • 2018-03-27 21:25:15
  • 2
收藏助手
不良信息举报
您举报文章:【树形DP】ZOJ - 3949 Edge to the Root
举报原因:
原因补充:

(最多只允许输入30个字)