zoukankan      html  css  js  c++  java
  • CF1266F

    题意

    给出一棵树,对于k=1~n求最大点集S满足dis(i,j)=k或k+1(i,j∈S & i≠j)

    题解

    首先答案满足ans[i]>=ans[i+2],因此可以维护后缀

    分类讨论

    ①k=1

    最大点集为最大度数+1

    ②k为奇数

    考虑一个中心点u,那么点集S满足任意一个在S中的点到u的距离为(k-1)/2或(k+1)/2,且最多只能有一个为(k-1)/2

    根据偶数的情况画一下,发现不能分成两个中心,然后又可以发现只能有一个特殊即可得到

    把度数排序,讨论一下特殊情况即可

    ③k为偶数

    分两种情况,第一种同k为奇数,只不过到u的距离只能为k/2

    第二种为一条边(u,v),S中的点满足以u为根时到v距离为k/2,或以v为根时到u距离为k/2

    这样暴力搞是O(n^2)的,但是可以发现不同深度的种类是(sqrt n)的,所以把深度相同的合并再做即可

    注意ans[i]至少为1

    时间复杂度:(O(nsqrt n))

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define max(a,b) (a>b?a:b)
    //#define file
    using namespace std;
    
    int a[1000001][3];
    int ls[500001];
    int ans[500001];
    int d[500001];
    int fd[500001];
    int b[500001];
    int deg[500001];
    int fa[500001];
    vector<int> c[500001];
    int n,i,j,k,l,len,tot;
    
    void New(int x,int y)
    {
    	++len;
    	a[len][0]=y;
    	a[len][1]=ls[x];
    	ls[x]=len;
    }
    
    void dfs(int Fa,int t)
    {
    	int i;
    	fa[t]=Fa;
    	
    	for (i=ls[t]; i; i=a[i][1])
    	if (a[i][0]!=Fa)
    	{
    		dfs(t,a[i][0]);
    		d[t]=max(d[t],d[a[i][0]]+1);
    	}
    }
    
    void Dfs(int Fa,int t,int D)
    {
    	int i,j,k,l,mx=0,Mx=-1,mx2=0;
    	fd[t]=D;tot=0;
    	
    	for (i=ls[t]; i; i=a[i][1])
    	if (a[i][0]!=Fa)
    	{
    		a[i][2]=d[a[i][0]]+1;
    		
    		if (d[a[i][0]]+1>mx)
    		mx2=mx,mx=d[a[i][0]]+1,Mx=a[i][0];
    		else
    		if (d[a[i][0]]+1>mx2)
    		mx2=d[a[i][0]]+1;
    		
    		b[++tot]=d[a[i][0]]+1;
    	}
    	else
    	a[i][2]=D;
    	if (D) b[++tot]=D;
    	
    	sort(b+1,b+tot+1);
    	j=0;
    	fo(i,1,tot)
    	{
    		if (b[i]==b[i-1])
    		++j;
    		else
    		j=1;
    		
    		if (i==tot || b[i]!=b[i+1])
    		c[t].push_back(b[i]),c[t].push_back(j);
    	}
    	
    	for (i=ls[t]; i; i=a[i][1])
    	if (a[i][0]!=Fa)
    	{
    		if (a[i][0]!=Mx)
    		Dfs(t,a[i][0],max(D,mx)+1);
    		else
    		Dfs(t,a[i][0],max(D,mx2)+1);
    	}
    }
    
    void work0() //k=1
    {
    	int t,i;
    	
    	fo(t,1,n)
    	{
    		for (i=ls[t]; i; i=a[i][1])
    		++deg[t];
    		
    		ans[1]=max(ans[1],deg[t]+1);
    	}
    }
    
    void work1() //one
    {
    	int N,t,i,j,k,l,sum,s1,s2;
    	
    	fo(t,1,n)
    	{
    		N=c[t].size()/2;
    		sum=deg[t];
    		
    		fo(i,1,N)
    		{
    			s1=c[t][i*2-2],s2=c[t][i*2-1];
    			
    			ans[s1*2]=max(ans[s1*2],sum); //even
    			
    			ans[s1*2-1]=max(ans[s1*2-1],sum); //odd
    			if (sum>s2)
    			ans[s1*2+1]=max(ans[s1*2+1],sum-s2+1);
    			
    			sum-=s2;
    		}
    	}
    }
    
    void work2() //two
    {
    	int N,x,y,d1,d2,i,j,k,l,n1,n2,sum1,sum2;
    	
    	fo(x,1,n)
    	{
    		for (i=ls[x]; i; i=a[i][1])
    		if (a[i][0]!=fa[x])
    		{
    			y=a[i][0];
    			d1=a[i][2];
    			d2=fd[y];
    			
    			n1=c[x].size();sum1=deg[x]-1;
    			n2=c[y].size();sum2=deg[y]-1;
    			
    			j=k=0;
    			while (j<n1 || k<n2)
    			{
    				if (j<n1 && c[x][j]==d1 && c[x][j+1]==1) j+=2;
    				if (k<n2 && c[y][k]==d2 && c[y][k+1]==1) k+=2;
    				
    				if (j<n1 && (k==n2 || c[x][j]<c[y][k]))
    				ans[c[x][j]*2]=max(ans[c[x][j]*2],sum1+sum2),sum1-=c[x][j+1],j+=2;
    				else
    				if (k<n2)
    				ans[c[y][k]*2]=max(ans[c[y][k]*2],sum1+sum2),sum2-=c[y][k+1],k+=2;
    			}
    		}
    	}
    }
    
    int main()
    {
    	#ifdef file
    	freopen("CF1266F.in","r",stdin);
    	#endif
    	
    	scanf("%d",&n);
    	fo(i,2,n)
    	{
    		scanf("%d%d",&j,&k);
    		
    		New(j,k);
    		New(k,j);
    	}
    	
    	ans[n-1]=ans[n]=1;
    	
    	dfs(0,1);
    	Dfs(0,1,0);
    	
    	work0();
    	work1();
    	work2();
    	
    	fd(i,n,3)
    	ans[i-2]=max(ans[i-2],ans[i]);
    	
    	fo(i,1,n)
    	printf("%d ",ans[i]);
    	printf("
    ");
    }
    
  • 相关阅读:
    整合Spring与Hibernate
    基本正则
    vue权限指令
    vue数字动态转换大写
    element ui 表格动态生成多级表头、一级表头,可无限嵌套
    vuex和vue-router全家桶
    element表格内容过多title提示
    HBuilder打包App方法
    mui底部选项卡切换页面
    mui框架的地步选项卡公用加载对应页面demo
  • 原文地址:https://www.cnblogs.com/gmh77/p/12116670.html
Copyright © 2011-2022 走看看