Title:
Give a tree with $n $dots, $m $queries. Give $x $for each query, and find the smallest $k $to break the $k $edge off the tree and reconnect the $k $edge to form a new tree. The tree's center of gravity is $x$.
$ $
The center of gravity of a tree: For every node in a rootless tree, the node with the largest subtree and the smallest subtree is the center of gravity.
$ $
Explanation:
First of all, we need to know a basic property of the center of gravity: if $x $is the center of gravity, then the $size $of each subtree rooted in $x $is less than or equal to \ frac{n}{2} (quite obvious?).
For the root node, we consider deleting at least a few subtrees of the root node so that the remaining $size of the root node is less than or equal to $\frac{n}{2}$.
If the $size $is less than or equal to $\frac{n}{2}$after deleting the previous $k$big sub-tree according to the size of the sub-tree, the number of times required for each node in the root node union block is equal to $k $or $k-1$. When a node is turned into a root, the $size $of its largest sub-tree must be the number of nodes in the previous union block minus the $size of all the sub-trees before it, so we want to reduce the $size of all the sub-trees before it. The number of nodes in a union block is calculated. Because the number of nodes in a union block must be less than or equal to $\frac{n}{2}$, it is enough to cut off the edge of $k$because we also need to subtract the number of nodes in a union block from its other subtrees, so it is possible to subtract the number of nodes in a union block from its other subtrees, and then it is less than or equal to $\frac{n}{2}$. The answer is $k or $k-1.
For deleting a node in a subtree, we imagine joining the subtree in which it is deleted to the root node and then turning it into a root, just as we did above.
Code:
#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]);//Because it's a random root, it's also possible for the size above the node to be its subtree. } 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);//Preprocessing for(int i=1;i<=n;i++) if(ma_s[i]<minn) rt=i,minn=ma_s[i];//Find the center of gravity of the original tree for(int i=head[rt];i;i=e[i].next) son[++temp]=e[i].to;//Find out the son whose center of gravity is 1 at all distances. dfs1(rt,0);//Change the original center of gravity to the root sort(son+1,son+1+temp,cmp);//Sort by subtree size for(int i=1;i<=temp;i++){ sum+=s[son[i]]; if(((sum+1)<<1)>n){ cx=i; break;//When size*2 is greater than n, it jumps out. } } for(int i=1;i<=temp;i++) dfs2(son[i],rt,sum-max(s[son[i]],s[son[cx]]));//Processing answers for(int i=1;i<=m;i++){ scanf("%d",&x); printf("%d\n",ans[x]);//query } return 0; }