标签:main F12 inline amp fine 特殊情况 while 因此 define
给出一棵树,对于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(n\sqrt n)\)
#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("\n");
}
标签:main F12 inline amp fine 特殊情况 while 因此 define
原文地址:https://www.cnblogs.com/gmh77/p/12116670.html