首页 > 其他分享 >CF708C Centroids [树形DP,换根DP]

CF708C Centroids [树形DP,换根DP]

时间:2024-10-08 13:50:28浏览次数:1  
标签:lfloor CF708C int siz Centroids rfloor mx DP size

Description

给定一棵树。
至多进行一次操作:删去一条边,连接一条新边,保证操作完后仍是树。
问每个点在进行操作后是否可以成为树的重心。

Solution

性质\(1\):若一个点不是树的重心,则它的必然有一个大小大于 \(\lfloor n/2\rfloor\) 的子树。

性质\(2\):如果一个点合法,要么它本来就是重心,要么它只有一个子树大于 \(\lfloor n/2\rfloor\),且从这个子树中移除一个最大的小于等于 \(\lfloor n/2\rfloor\) 的子树可以使它自己也小于等于 \(\lfloor n/2\rfloor\)。

考虑 树形dp,设 \(f(u)\) 表示以 \(u\) 为根的子树中,最大的不超过 \(\lfloor n/2\rfloor\) 的子树大小,初始先以 \(1\) 为总根,转移如下,
当 \(size_v\le \lfloor n/2\rfloor\) 时,\(f(u) = \max(f(u),size_v)\),
否则 \(f(u) = \max(f(u),f(v))\),
\(v\in son_u\)。

考虑如何处理子树外的答案,即换根,设 \(g(u)\) 表示不在以 \(u\) 为根的子树内的答案,
为了方便转移,我们需要更改一下状态 \(f\),设 \(f(u,0/1)\) 分别表示最大答案和次大答案,转移和原来类似,然后还要记录一下每个点的最佳转移状态,就是它最终是由哪个点转移过来的,
\(g\) 的转移如下,
当 \(f(u,0)\) 的最佳转移是 \(v\) 时,

  • 如果 \(n-size_u\le \lfloor n/2\rfloor\),那么 \(g(v) = \max(g(u),n-size_u,f(u,1))\),
  • 否则 \(g(v) = \max(g(u),f(u,1))\),

否则,

  • 如果 \(n-size_u\le \lfloor n/2\rfloor\),那么 \(g(v) = \max(g(u),n-size_u,f(u,0))\),
  • 否则 \(g(v) = \max(g(u),f(u,0))\)。

最终根据性质\(2\),判断每个点是否合法即可。

Code

const int N = 4e5 + 5;

int n;

vector <int> e[N];

int siz[N], f[N][2], mx[N]; // f(u) : 以 u 为根的子树内满足大小 <=n/2 的最大和次大子树大小 (整棵树以 1 为根)
                            // mx(u) : 记录 f(u) 的最佳转移 v
int g[N];
bool ans[N];

void dfsF(int u, int fa){
    siz[u] = 1;
    for(int v : e[u]){
        if(v == fa) continue;
        dfsF(v, u);
        siz[u] += siz[v];
        if(siz[v] <= n / 2){
            if(siz[v] > f[u][0]){ // 最大和次大不能从同一个子树转移!
                f[u][1] = f[u][0];
                f[u][0] = siz[v];
                mx[u] = v;
            }else if(siz[v] > f[u][1]) f[u][1] = siz[v];
        }
        else{
            if(f[v][0] > f[u][0]){
                f[u][1] = f[u][0];
                f[u][0] = f[v][0];
                mx[u] = v;
            }else if(f[v][0] > f[u][1]) f[u][1] = f[v][0];
        }
    }
}

void dfsG(int u, int fa){
    for(int v : e[u]){
        if(v == fa) continue;
        if(mx[u] == v){
            if(n - siz[u] <= n / 2) g[v] = max(f[u][1], n - siz[u]);
            else g[v] = max(f[u][1], g[u]);
        }else{
            if(n - siz[u] <= n / 2) g[v] = max(f[u][0], n - siz[u]);
            else g[v] = max(f[u][0], g[u]);
        }
        dfsG(v, u);
    }
}

void dfsAns(int u, int fa){
    int mx = n - siz[u];
    int cnt = 0, id = -1;
    if(mx > n / 2) id = fa, cnt++;

    for(int v : e[u]){
        if(v == fa) continue;
        if(siz[v] > n / 2){
            mx = siz[v];
            id = v;
            cnt++;
        }
        dfsAns(v, u);
    }

    if(cnt == 0) ans[u] = true;
    else if(cnt == 1 && id == fa && mx - g[u] <= n / 2) ans[u] = true;
    else if(cnt == 1 && id != fa && mx - f[id][0] <= n / 2) ans[u] = true;
    else ans[u] = false;
}

void Solve(){
    cin >> n;
    int u, v;
    for(int i = 1; i <= n - 1; i++){
        cin >> u >> v;
        e[u].ps(v);
        e[v].ps(u);
    }

    dfsF(1, 0);
    dfsG(1, 0);
    dfsAns(1, 0);

    for(int i = 1; i <= n; i++) cout << ans[i] << ' ';
}

标签:lfloor,CF708C,int,siz,Centroids,rfloor,mx,DP,size
From: https://www.cnblogs.com/chenwenmo/p/18451488

相关文章

  • CF708C Centroids [树形DP,换根DP]
    Description给定一棵树。至多进行一次操作:删去一条边,连接一条新边,保证操作完后仍是树。问每个点在进行操作后是否可以成为树的重心。Solution性质\(1\):若一个点不是树的重心,则它的必然有一个大小大于\(\lfloorn/2\rfloor\)的子树。性质\(2\):如果一个点合法,要么它本来......
  • DP套DP
    该技巧通常用来求满足某个要求的元素数量,而对于要求的判定需要DP解决。因此我们将判定DP的结果作为计数DP的状态来进行计数。P4590[TJOI2018]游园会题意:给你一个字符串\(s\),求满足条件的字符串\(t\)的数量:\(\vertt\vert=n,\\text{lcs}(s,t)=i,\\text{"NOI"}......
  • E61 树形DP P8744 [蓝桥杯 2021 省 A] 左孩子右兄弟
    视频链接:  P8744[蓝桥杯2021省A]左孩子右兄弟-洛谷|计算机科学教育新生态(luogu.com.cn)//树形DPO(n)#include<bits/stdc++.h>usingnamespacestd;constintN=100005;intn,f[N],son[N];inthead[N],idx;structE{intv,ne;}e[N<<1];voidadd(intu......
  • 树上深度和问题 - 换根DP
    问题引出:给出\(n\)个点的树,求出分别以不同的\(i\)为根时,所有结点深度的和,根节点的深度为\(0\)。首先我们有个自然的暴力思路,也就是以每个节点为根节点做一遍\(dfs\)这样的复杂度是\(O(n^2)\)级别的,所以要进行优化看下图:我们首先假设每个节点具有点权,明显这......
  • NOIP 前 dp 做题小记
    NOIP前dp做题小记[BJOI2019]排兵布阵设\(f(i,j)\)表示在前\(i\)个城堡中总共派遣\(j\)个士兵时,可以获得的最大分数。初始化:\(\forall0\lej\lem\),\(f(0,j)=0\)答案统计:\(ans=f(n,m)\)转移:\(f(i,j)=\max_{0\lek\lej}f(i-1,j-k)+g(i,k)......
  • 斜率优化 DP
    斜率优化DP在单调队列优化过程中,转移方程被拆成了两部分,第一部分仅与\(j\)有关,而另一部分仅与\(i\)有关,因此我们可以利用单调队列仅维护与\(j\)有关的部分,实现问题的快速求解。但仍然有很多转移方程,\(i\)和\(j\)是紧密相关的,这个时候单调队列优化就不适用了,例如如下转......
  • DP 套 DP(DP of DP)
    把DP过程当作状态进行DP。DPofDP一般数据范围不会太大,而且一般是计数题。DPofDP的本质是自动机上DP。大致上可以写作\(dp[\dots][S]\)表示外层DP进行到\(\dots\)阶段,内层DP对应到\(S\)阶段。例一:基因题意:给出串\(s\)和一个数\(m\)。\(n=|s|\)。求对于......
  • TCPUDP 共用端口问题
    TCP/UDP共用端口问题。转载自:TCP/UDP占用端口问题总结-mengban-博客园(cnblogs.com)1.TCPUDP可以共同占用一个端口号吗?首先明确一点端口是一种抽象的软件结构(包括一些数据结构和I/O缓冲区)。应用程序(即进程)通过系统调用与某端口建立连接(binding)后,传输层传给该端口......
  • 基于DPAPI+RDP技术实现本地打开远程程序,并映射到本地机器桌面上
    本教程使用工具所使用的环境说明:启动器开发工具:VS2022启动器所用客户端技术:.NET8+WPF启动器其他技术:DPAPI启动器发布的可执行程序,系统要求:Windows7以及以上,X64如果需要本程序,可以在网盘获取。网盘地址:链接:https://pan.baidu.com/s/1QPstE5-1zPK-qOp8GQ90ew?pwd=6666......
  • CodeForces - 118D - dp
    这道题的思路可能来源于步兵后面必须跟骑兵,反之亦然,那么一个兵种当前的状态肯定是由另一个兵种上一个的状态推来的(即取用该当前取用的兵种之前)。接下来就要考虑怎么控制每次取用多少个人了,由题意可知,每次取用不得超过k1或k2,我们从1-n1和从1-n2表示骑兵和步兵当前的数量表示......