首页 > 其他分享 >ICPC2022Xian L Tree 题解

ICPC2022Xian L Tree 题解

时间:2023-11-29 16:47:49浏览次数:54  
标签:ICPC2022Xian ch int 题解 Tree ret son dep 节点

Link

ICPC2022Xian L Tree

Question

给出一个根为 \(1\) 的树,需要将树分成几个块每个块,一个块中的节点需要满足以下条件中的一个:

  • 对于所有的 \(u,v \in S,\ u \neq v\) ,满足 \(u \in subtree(v)\) 或 \(v \in subtree(u)\)

  • 对于所有的 \(u,v \in S,\ u \neq v\) ,满足 \(u \not\in subtree(v)\) 且 \(v \not\in subtree(u)\)

求把树分成的最小块数

Solve

先翻译题目,第一个条件是一条链上的点满足,第二个条件是不同子树上的点满足

只考虑第一种情况,贪心的去想,如果选了 \(x\) ,那么再选一个 \(x\) 的子节点并不会增加块数,那么就尽可能多得去选择,也就是取 \(x\) 往下长的链,那么块数就是长链剖分后的链数

只考虑第二种情况,如果给定一颗树,那么最少的块数就是数最深的节点的深度

image.png

因为假设选了 \(x\) ,那么 \(x\) 的祖先节点就不能和 \(x\) 在一个块里面,所以假设 \(x\) 的深度为 \(dep[x]\) 则,这条链就需要开 \(dep[x]\) 个块,每个块一个节点,对于不同链的节点,把深度相同的放在一个块里面,所以块数就是最深的那个点的深度

对于一颗树,我们从根节点找最长的链,我们发现,最长链的长度就是 \(Max(dep[x])\) ,但由于不知道到底要取多少条链,就枚举链的条数。贪心的想,我们肯定先取长的链,就先预处理出每条链的长度,设为 \(Len_i\) ,假设取了 \(i\) 条链,剩下的节点需要分的块数就是 \(Len_{i+1}\) 所以,总的块数就是 \(i+Len_{i+1}\),求一个最小值就是答案

Code

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int ret=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    return ret*f;
}

const int maxn=1e6+5;
vector<int> dep;
vector<vector<int> > E;
vector<int> son;
vector<int> p;
void dfs1(int x){
    for(auto u: E[x]){
        dfs1(u);
        if(son[x]==0||dep[u]>dep[son[x]]) son[x]=u;
    }
    dep[x]=dep[son[x]]+1;
}
void dfs2(int x,int now_l){
    if(!son[x]) p.push_back(now_l);
    else {
        dfs2(son[x],now_l+1);
        for(auto u:E[x]) {
            if(u!=son[x])
                dfs2(u,1);
        }
    } 
}
inline void solve(){
    int N=read();
    p.clear();
    dep.assign(N+1,0);
    son.assign(N+1,0);
    E.resize(N+1);
    for(auto& x:E){
        x.clear();
    }

    for(int i=2;i<=N;i++){
        int fa=read();
        E[fa].push_back(i);
    }
    dfs1(1);
    dfs2(1,1);
    sort(p.begin(),p.end(),greater<int>());
    int num=p.size(),ans=num;
    for(int i=0;i<num-1;i++){
        int now_ans=i+p[i+1]+1;
        ans=min(now_ans,ans);
    }
    cout<<ans<<endl;
    return ;
}
int main(){
    freopen("L.in","r",stdin);
    int T=read();
    while(T--) solve();
}

标签:ICPC2022Xian,ch,int,题解,Tree,ret,son,dep,节点
From: https://www.cnblogs.com/martian148/p/17865219.html

相关文章

  • python ElementTree操作xml节点
    pythonElementTree操作xml节点,包括增删改查xml原文<Voucher><Id>967a198783d14835860574c697478156</Id><Remark>main摘要443344245567583384475</Remark><Delete>需要删除的节点1</Delete><DetailList><Detail......
  • [ABC277G] Random Walk to Millionaire 题解
    题目链接点击打开链接题目解法首先\(O(n^3)\)的\(dp\)是显然的,令\(f_{i,j,k}\)为第\(i\)步在\(j\),当前等级为\(k\)的\([i,n]\)步获得钱数的期望,转移枚举出边即可一个很妙的优化是:贡献都是\(k^2\)的形式,所以我们考虑维护\(k\)的\(0,1,2\)次幂,即\(\sum,\sum......
  • CF1900D - Small GCD 题解
    1900D-SmallGCD给定序列\(A\),定义\(f(a,b,c)\)为\(a,b,c\)中最小的次小的数的\(\gcd\),求:\[\sum_{i=1}^n\sum_{j=i+1}^n\sum_{k=j+1}^nf(a_i,a_j,a_k)\]题解目前来说有两种方法,都十分有启发意义,但是有共同的开头。考虑到\(A\)的顺序实际上没有......
  • SP19543 GSS8 - Can you answer these queries VIII 题解
    更好的阅读体验SP19543GSS8-CanyouanswerthesequeriesVIIIfhq+二项式定理。提供一个不太一样的思路。默认下标从\(1\)开始。首先插入删除,区间查询,想到可以平衡树维护或者离线下来做线段树。本文中是用的是fhq,好写一些。\(k\)非常的小,考虑对于每一个\(k\)的答......
  • 如何动态展开el-tree的某个子节点
    需求:当添加文件夹或者表单时展开该节点addChildDirectory(node,data){this.$nextTick(()=>{//重命名时展开改文件夹this.$refs.tree.store.nodesMap[data.id].expanded=true;});}结果:后面还有如何添加文件夹的内容,如何在鼠标移动到文字......
  • 服务器数据库A的备份恢复到服务器B后出现问题解决
    消息10314,级别16,状态11,第2行尝试加载程序集ID65536时,Microsoft.NETFramework出错。服务器可能资源不足,或者程序集可能不受信任,PERMISSION_SET=EXTERNAL_ACCESS或UNSAFE。如上错误提示,解决办法: alterdatabasedatabasenamesettrustworthyon还有更改数据库......
  • CF1901E Compressed Tree(树dp)
    Problem题目地址Solution来自fcy大佬的思路记\(f_u\)表示假定以\(u\)为根的子树,在压缩后,(子树内的某一个点(包括\(u\)))可以向外(除\(u\)为根的子树外所以点的集合)连一条边时的最大\(sum\)。换言之,我们把树拆成以\(u\)为根的子树(记作\(Tree_u\))和非\(Tree_u\)部分。而......
  • 【题解】CF1550E Stringforces
    标签:DP\(B^+\)阅读须知:本题解较为详细地讲述的该题解法的思路和来龙去脉,但篇幅较长,请耐心阅读。Step1从题面获取信息我们考虑,因为最大值最小,所以我们首先想到二分答案。然后我们又看到\(k\leq17\)这个限制,所以会想到可能是关于一个\(2^k\)之类的复杂度。以上就是我......
  • ABC330 E Mex and Update 题解
    LinkABC330EMexandUpdateQuestion给一个数组\(a\),有\(Q\)次修改每次把\(a_i\)改成\(x\)问每次修改后,不在\(a\)数组中的最小非负数时多少Solution记录每个\(a_i\)出现的次数\(num\)每个修改操作可以看成时先删除,后添加用set维护为\(num_x=0\)的\(x\)......
  • [ABC321E] Complete Binary Tree
    思路:第一次先把往后距离为$k$的点算出来,然后再每次往前走一个,考虑$k-i$的情况。(具体见代码注释)。代码:```cpp#include<bits/stdc++.h>usingnamespacestd;//headintsum[100],head=0;intn,x,k;intans;voidf(intnow,intstep)//从点now开始,往上距离step的点的个数......