CF1527D
AsunderSquall · · 题解
题意
给一棵
题解
whk 了两个月之后感觉自己已经没有脑子了(奇怪,说得好像我曾经有过一样)。
首先考虑在链上怎么做。我们从
那么我们发现
然后我们考虑怎么上树。首先,如果
我维护链的方法是,如果当前点不在链上,就不停地跳父亲直到找到已经在链上的点。如果是端点,那么就产生了新的端点,否则一定不是一条链。链两端的节点数可以直接用子树大小。
代码:
实现非常丑陋(最开始的时候甚至把一个 bool 数组能干的事用 set 来做,我果然没脑子)
int n,ans,m,l,r,L,R;
int a[N],b[N],sz1[N],sz2[N],FA[N],S[N];
vector<int> T[N];
void dfs(int u,int fa,int sz[])
{
FA[u]=fa;
sz[u]=1;for (int v:T[u]) if (v!=fa) dfs(v,u,sz),sz[u]+=sz[v];
}
signed main()
{
int qwq;rd(qwq);while (qwq--)
{
rd(n);
for (int i=0;i<=n;i++) T[i].clear();
for (int i=1,x,y;i<n;i++) rd(x),rd(y),T[x].push_back(y),T[y].push_back(x);
for (int i=0;i<=n+1;i++) a[i]=0,sz1[i]=sz2[i]=0,S[i]=0;
l=r=0;dfs(0,-1,sz1);a[0]=n*(n-1)/2;
a[1]=2*n-2;for (int v:T[0]) a[1]+=(n-1-sz1[v])*sz1[v];a[1]/=2;
dfs(1,-1,sz2);l=1;r=0;L=sz1[l];R=sz2[r];a[2]=L*R;
int x=0;while (x!=1) S[x]=1,x=FA[x];S[1]=1;
for (int k=2;k<n;k++)
{
if (S[k]) {a[k+1]=L*R;continue;}
int x=k;
while (!S[x]) x=FA[x];
if (x==l)
{
int x=k;while (x!=l) S[x]=1,x=FA[x];
l=k,L=sz1[l],a[k+1]=L*R;
} else if (x==r)
{
int x=k;while (x!=r) S[x]=1,x=FA[x];
r=k;R=sz2[r],a[k+1]=L*R;
} else break;
}
for (int i=0;i<=n;i++) a[i]-=a[i+1],cout<<a[i]<<" ";
puts("");
}
}