题意
给出一棵树,对于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)\)
code
#include
#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 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