2 条题解

  • 0
    @ 2025-11-10 19:33:01
    // 树形DP O(n)
    #include<bits/stdc++.h>
    using namespace std;
    
    int read(){
      int x=0,f=1;char c=getchar();
      while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}
      while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
      return x*f;
    }
    const int N=200005;
    int n,T,ans;
    vector<int> e[N];
    int d[N],f[N],g[N],h[N];
    int D[N][3],S[N][3];
    
    void upd(int u,int v,int dv){
      if(dv>=D[u][0]){
        D[u][2]=D[u][1];S[u][2]=S[u][1];
        D[u][1]=D[u][0];S[u][1]=S[u][0];
        D[u][0]=dv;S[u][0]=v;
      }
      else if(dv>=D[u][1]){
        D[u][2]=D[u][1];S[u][2]=S[u][1];
        D[u][1]=dv;S[u][1]=v;
      } 
      else if(dv>D[u][2])D[u][2]=dv,S[u][2]=v;
    }
    void dfs(int u){
      int f1=0,f2=0;
      for(int v:e[u]){
        dfs(v);
        d[u]=max(d[u],d[v]+1); 
        upd(u,v,d[v]);
        f[u]=max(f[u],f[v]);  
        g[u]=max(g[u],g[v]+1);
        h[u]=max(h[u],h[v]);  
        if(f[v]>f1) f2=f1,f1=f[v];
        else if(f[v]>f2) f2=f[v];
      }
      f[u]=max(f[u],D[u][0]+D[u][1]+2);
      h[u]=max(h[u],f1+f2);
      
      for(int v:e[u]){
        g[u]=max(g[u],f[v]+(S[u][0]==v?D[u][1]:D[u][0])+1);
        int res=0,cnt=0;
        if(S[u][0]!=v) res+=D[u][0],cnt++;
        if(S[u][1]!=v) res+=D[u][1],cnt++;
        if(cnt<2&&S[u][2]!=v) res+=D[u][2];
        h[u]=max(h[u],f[v]+res+2);
        h[u]=max(h[u],g[v]+(S[u][0]==v?D[u][1]:D[u][0])+2);
      }
    }
    int main(){
    
      T=read();
      while(T--){
        n=read();
        for(int i=1;i<=n;i++){
          e[i].clear();
          for(int j=0;j<=2;j++)D[i][j]=-1,S[i][j]=0;
          d[i]=f[i]=h[i]=0; g[i]=-1;
        }
        for(int i=2,x;i<=n;i++)
          x=read(),e[x].push_back(i);
        dfs(1);
        int mx1=-1,mx2=-1; ans=0;
        for(int i:e[1]){
          if(f[i]>mx1) mx2=mx1,mx1=f[i];
          else if(f[i]>mx2) mx2=f[i];
          ans=max(ans,h[i]+2);
        }
        ans=max(ans,mx1+mx2+2);
        if(n==2) ans=1;
        printf("%d\n",ans);      
      }
      return 0;
    }
    
    
    
    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned long long LL;
    int N[]={0,10,20,90,200000,200000};
    int T[]={0,10000,10000,10000,10000,15};
    int M[]={0,3,3,4,3,7};
    char infile[100];
    char outfile[100];
    char cmd[100];
    int random(int l,int r)//产生一个范围[l,r]的数 
    {
    	return (LL)rand()*rand()*rand()%(r-l+1)+l;
    	//rand()是系统函数,只能产生[0,32767]的数 
    	//rand()*rand()==1,073,676,289
    }
    int main()
    {
    	srand(time(0));
    	for(int t=1;t<=5;t++)for(int mi=1;mi<=M[t];mi++)
    	{
    		sprintf(infile,"a%d%d.in",t,mi);
    		sprintf(outfile,"a%d%d.out",t,mi);
    		freopen(infile,"w",stdout);
    		printf("%d\n",T[t]);
    		while(T[t]--){
    			int n=N[t];
    			printf("%d\n",n);
    			for(int i=2;i<=n;i++){
    				int x=random(1,i-1);
    				printf("%d ",x);
    			}
    			printf("\n");
    		}
    		fclose(stdout);
    		
    		// 假设 std 在当前目录
    		sprintf(cmd,"std.exe < %s > %s",infile,outfile);
    		int result = system(cmd);
    		if(result != 0) {
    			fprintf(stderr,"运行 std 失败,文件: %s\n", infile);
    		} else {
    			fprintf(stderr,"正在制造第 %d 组数据\n",t);
    		}
    	}
    }
    
    • 0
      @ 2025-11-10 14:28:41

      E93 树形DP+树的直径 P10794『SpOI - R1』架子鼓可以站 C

      // 树形DP O(n)
      #include<bits/stdc++.h>
      using namespace std;
      
      int read(){
        int x=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
      }
      const int N=200005;
      int n,T,ans;
      vector<int> e[N];
      int d[N],f[N],g[N],h[N];
      int D[N][3],S[N][3];
      
      void upd(int u,int v,int dv){
        if(dv>=D[u][0]){
          D[u][2]=D[u][1];S[u][2]=S[u][1];
          D[u][1]=D[u][0];S[u][1]=S[u][0];
          D[u][0]=dv;S[u][0]=v;
        }
        else if(dv>=D[u][1]){
          D[u][2]=D[u][1];S[u][2]=S[u][1];
          D[u][1]=dv;S[u][1]=v;
        } 
        else if(dv>D[u][2])D[u][2]=dv,S[u][2]=v;
      }
      void dfs(int u){
        int f1=0,f2=0;
        for(int v:e[u]){
          dfs(v);
          d[u]=max(d[u],d[v]+1); 
          upd(u,v,d[v]);
          f[u]=max(f[u],f[v]);  
          g[u]=max(g[u],g[v]+1);
          h[u]=max(h[u],h[v]);  
          if(f[v]>f1) f2=f1,f1=f[v];
          else if(f[v]>f2) f2=f[v];
        }
        f[u]=max(f[u],D[u][0]+D[u][1]+2);
        h[u]=max(h[u],f1+f2);
        
        for(int v:e[u]){
          g[u]=max(g[u],f[v]+(S[u][0]==v?D[u][1]:D[u][0])+1);
          int res=0,cnt=0;
          if(S[u][0]!=v) res+=D[u][0],cnt++;
          if(S[u][1]!=v) res+=D[u][1],cnt++;
          if(cnt<2&&S[u][2]!=v) res+=D[u][2];
          h[u]=max(h[u],f[v]+res+2);
          h[u]=max(h[u],g[v]+(S[u][0]==v?D[u][1]:D[u][0])+2);
        }
      }
      int main(){
        T=read();
        while(T--){
          n=read();
          for(int i=1;i<=n;i++){
            e[i].clear();
            for(int j=0;j<=2;j++)D[i][j]=-1,S[i][j]=0;
            d[i]=f[i]=h[i]=0; g[i]=-1;
          }
          for(int i=2,x;i<=n;i++)
            x=read(),e[x].push_back(i);
          dfs(1);
          int mx1=-1,mx2=-1; ans=0;
          for(int i:e[1]){
            if(f[i]>mx1) mx2=mx1,mx1=f[i];
            else if(f[i]>mx2) mx2=f[i];
            ans=max(ans,h[i]+2);
          }
          ans=max(ans,mx1+mx2+2);
          if(n==2) ans=1;
          printf("%d\n",ans);      
        }
      }
      
      • 1

      E93 树形DP+树的直径 『SpOI - R1』架子鼓可以站 C

      信息

      ID
      7206
      时间
      2000ms
      内存
      512MiB
      难度
      10
      标签
      递交数
      2
      已通过
      1
      上传者