#树,搜索#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;
}
posted @ 2020-10-14 20:12  lemondinosaur  阅读(74)  评论(0编辑  收藏  举报