#樹,搜尋#NOIP2020.9.26模擬tom
阿新 • • 發佈:2020-10-14
分析
考慮最極端的情況也就是TOM天天吃早餐腸或者晚餐腸, 那麼早餐腸和晚餐腸應分別構成一個互不相交連通塊, 所以題目轉換成是否有一個點的子樹大小為$a$或$b$, 將這個點與它父親的邊斷開就可以分別編號了
程式碼
#include <cstdio> #include <cctype> #include <queue> #define rr register using namespace std; const int N=100011; struct node{int y,next;}e[N<<1]; int a[N],n,k=1,son[N],rt1,rt2,now,as[N],A,B; inline signed iut(){ rr int ans=0; rr char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar(); return ans; } inline void print(int ans){ if (ans>9) print(ans/10); putchar(ans%10+48); } inline void dfs1(int x,int fa){ son[x]=1; for (rr int i=as[x];i;i=e[i].next) if (e[i].y!=fa) dfs1(e[i].y,x),son[x]+=son[e[i].y]; if (son[x]==A) rt1=x,rt2=fa; else if (son[x]==B) rt1=fa,rt2=x; } inline void dfs2(int x,int opt,int fa){ a[x]=opt*(now--); for (rr int i=as[x];i;i=e[i].next) if (!a[e[i].y]&&e[i].y!=fa) dfs2(e[i].y,opt,fa); } signed main(){ freopen("tom.in","r",stdin); freopen("tom.out","w",stdout); n=iut(); A=iut(); B=iut(); for (rr int i=1;i<n;++i){ rr int x=iut(),y=iut(); e[++k]=(node){y,as[x]},as[x]=k; e[++k]=(node){x,as[y]},as[y]=k; } dfs1(1,0); if (!rt1&&!rt2) return !printf("-1"); now=A,dfs2(rt1,1,rt2),now=B,dfs2(rt2,-1,rt1); for (rr int i=1;i<=n;++i){ if (a[i]<0) putchar('-'),print(-a[i]); else print(a[i]); putchar(10); } return 0; }