#树,搜索#NOIP2020.9.26模拟tom
分析
考虑最极端的情况也就是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;
}