题意:
给一棵 $n$ 个点的树 , 有$m$次询问. 每次询问给出$x$, 求一个最小的$k$使得把树上$k$条边断掉然后重新连$k$条边形成一棵新的树之后, 树的重心为$x$.
$ $
树的重心:对于一棵无根树上的每个节点 , 将其变成根之后 , 最大子树大小最小的节点便是重心 .
$ $
题解:
首先要知道重心的一个基本性质:若$x$是重心 , 那么以$x$为根的每棵子树的$size$都小于等于$\frac{n}{2}$(挺显然的?.
我们对于根节点 , 考虑最少删掉根节点的几棵子树 , 使得根节点剩余的$size$小于等于$\frac{n}{2}$ .
若按照子树大小排序后删去前$k$大棵子树之后满足$size$小于等于$\frac{n}{2}$ , 对于还在根节点联通块内的每个节点 , 要求的次数等于$k$或$k-1$ . 将某个节点变成根之后 , 其最大子树的$size$肯定是其之前所处的联通块内节点数减去它之前的所有子树的$size$ , 所以我们要用算出联通块中节点数量 . 又因为联通块中节点数量必定满足小于等于$\frac{n}{2}$ , 所以就是断掉$k$条边即可 ; 因为我们还要用联通块中节点数量减去它的其他子树 , 所以可能只用删$k-1$棵子树就满足联通块中节点数量减去它的其他子树后小于等于$\frac{n}{2}$ , 于是乎答案就为$k$或$k-1$ .
对于在删去子树中的节点 , 我们想象一下删去之后把它所在的子树接在根节点再把它变为根 , 就和上面的操作一样了 .
代码:
#include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; const int N=1e6+5; int n,m,tot,rt,temp,minn=INF,sum,cx; int head[N],s[N],ma_s[N],son[N],ans[N]; struct Edge{ int next,to; }e[N<<1]; inline void add_edge(int from,int to){ e[++tot].next=head[from]; e[tot].to=to; head[from]=tot; } void dfs1(int now,int fa){ s[now]=1; for(int i=head[now];i;i=e[i].next){ int v=e[i].to; if(v==fa) continue; dfs1(v,now); s[now]+=s[v]; ma_s[now]=max(ma_s[now],s[v]); } ma_s[now]=max(ma_s[now],n-s[now]);//因为是随便取的根所以对于节点上面的size也有可能是它的子树 } bool cmp(int x,int y){return s[x]>s[y];} void dfs2(int now,int fa,int size){ ans[now]=cx-(((n-s[now]-size)<<1)<=n); for(int i=head[now];i;i=e[i].next) if(e[i].to!=fa) dfs2(e[i].to,now,size); } int main(){ freopen("chemistry.in","r",stdin); freopen("chemistry.out","w",stdout); scanf("%d%d",&n,&m); int x,y; for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); add_edge(x,y); add_edge(y,x); } dfs1(1,0);//预处理 for(int i=1;i<=n;i++) if(ma_s[i]<minn) rt=i,minn=ma_s[i];//找出原树重心 for(int i=head[rt];i;i=e[i].next) son[++temp]=e[i].to;//求出原重心的所有距离为1的儿子 dfs1(rt,0);//把原重心变为根 sort(son+1,son+1+temp,cmp);//按子树大小排序 for(int i=1;i<=temp;i++){ sum+=s[son[i]]; if(((sum+1)<<1)>n){ cx=i; break;//加上自身后size*2大于n就跳出 } } for(int i=1;i<=temp;i++) dfs2(son[i],rt,sum-max(s[son[i]],s[son[cx]]));//处理答案 for(int i=1;i<=m;i++){ scanf("%d",&x); printf("%d\n",ans[x]);//查询 } return 0; }