CF708C Centroids
题意翻译
给定一颗树,你有一次将树改造的机会,改造的意思是删去一条边,再加入一条边,保证改造后还是一棵树。
请问有多少点可以通过改造,成为这颗树的中心?(如果以某个点为根,每个子树的大小都小于n/2,则称某个点为中心)
sol:先找到整颗树的重心,然后对于每个点,肯定是把重心的最大子树串过来最优(XJByy一下),如果这个点在最大子树中,就搞来次大子树,或者把除了最大子树的剩下一大坨串过来
#include <bits/stdc++.h> using namespace std; typedef int ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) {f|=(ch=='-'); ch=getchar();} while(isdigit(ch)) {s=(s<<3)+(s<<1)+(ch^48); ch=getchar();} return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) {putchar('-'); x=-x;} if(x<10) {putchar(x+'0'); return;} write(x/10); putchar((x%10)+'0'); } #define W(x) write(x),putchar(' ') #define Wl(x) write(x),putchar(' ') const int N=400005,M=800005; int n,rt,t1=0,t2=0,sz[N],mx[N]; int tot=0,Next[M],to[M],head[N]; bool bo[N]; inline void Link(int x,int y) { Next[++tot]=head[x]; to[tot]=y; head[x]=tot; } inline void getrt(int x,int fat) { int e; sz[x]=1; mx[x]=0; for(e=head[x];e;e=Next[e]) if(to[e]!=fat) { getrt(to[e],x); sz[x]+=sz[to[e]]; mx[x]=max(mx[x],sz[to[e]]); } mx[x]=max(mx[x],n-sz[x]); if(mx[x]<mx[rt]) rt=x; } inline void dfs(int x,int fat) { int e; sz[x]=1; for(e=head[x];e;e=Next[e]) if(to[e]!=fat) { dfs(to[e],x); sz[x]+=sz[to[e]]; } } inline void draw(int x,int fat) { int e; bo[x]=1; for(e=head[x];e;e=Next[e]) if(to[e]!=fat) { draw(to[e],x); } } int main() { freopen("data.in","r",stdin); int i,x,y; R(n); for(i=1;i<n;i++) { R(x); R(y); Link(x,y); Link(y,x); } mx[rt=0]=n+1; sz[0]=0; getrt(1,0); dfs(rt,0); for(i=head[rt];i;i=Next[i]) { if(sz[to[i]]>sz[t1]) t2=t1,t1=to[i]; else if(sz[to[i]]>sz[t2]) t2=to[i]; } if(t1) draw(t1,rt); // cout<<"rt="<<rt<<endl; // for(i=1;i<=n;i++) cout<<bo[i]<<' '; puts(""); for(x=1;x<=n;x++) { if(!bo[x]) { if((n-sz[x]-sz[t1])*2<=n) putchar('1'); else putchar('0'); } else { if((n-sz[x]-sz[t2])*2<=n) putchar('1'); else if((n-sz[t1])*2<=n) putchar('1'); else putchar('0'); } putchar(' '); } return 0; }