3 条题解

  • 0
    @ 2025-10-4 19:22:22

    写一个有点丑陋的做法

    首先我们考虑有一个很 navienavie 的贪心,lzdlzd 已经说过了,不再赘述

    然后我们直接考虑怎么做

    我们直接设 fif_i 表示我当前有一红一蓝在 ii 点上

    然后我们考虑转移

    我们发现我们一定是从我子树下面某一个固定深度的点转移

    然后我们只要快速找到这棵子树下面的某一深度的所有点就好了

    然后我们可以用 dfndfn 序来做这件事情

    然后就秒了

    CODE

    #include<bits/stdc++.h>
    using namespace std;
    bool lf[200005];
    vector<int>G[200005];
    vector<int>ids[200005];
    int dep[200005],dfn[200005],redfn[200005],siz[200005];
    int mn[200005];
    void dfs(int x){
    	mn[x]=100000000;
    	siz[x]=1;
    	dfn[x]=++dfn[0];
    	ids[dep[x]].push_back(dfn[x]);
    	redfn[dfn[0]]=x;
    	if(lf[x])mn[x]=dep[x];
    	for(int i=0; i<(int)G[x].size(); i++){
    		int y=G[x][i];
    		dep[y]=dep[x]+1;
    		dfs(y);
    		mn[x]=min(mn[x],mn[y]);
    		siz[x]+=siz[y];
    	}
    }
    int f[200005];
    void dfs2(int x){
    	if(mn[x]==dep[x]){
    //		f[x]=1;
    		return;
    	}
    	int be=lower_bound(ids[mn[x]].begin(),ids[mn[x]].end(),dfn[x])-ids[mn[x]].begin();
    	for(int i=be; i<(int)ids[mn[x]].size(); i++){
    		int dn=ids[mn[x]][i];
    		if(dn>dfn[x]+siz[x]-1){break;}
    		dfs2(redfn[dn]);
    		f[x]=max(f[x],f[redfn[dn]]);
    	}f[x]++;
    }
    int main(){
    	freopen("tree.in","r",stdin);
    	freopen("tree.out","w",stdout);
    	int n,p;scanf("%d",&n);
    	memset(lf,1,sizeof lf);
    	for(int i=2; i<=n; i++){
    		scanf("%d",&p);G[p].push_back(i);
    		lf[p]=0;
    	}dfs(1),dfs2(1);
    	cout<<f[1];
    	return 0;
    } 
    
    

    信息

    ID
    446
    时间
    1000ms
    内存
    256MiB
    难度
    8
    标签
    (无)
    递交数
    16
    已通过
    5
    上传者