Summer vacation training 2019.08.01 chemistry

Keywords: PHP less

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;
}

Posted by Volte on Tue, 08 Oct 2019 01:23:12 -0700