九校联考--长沙一中day2t1tom

Description

众所周知, Tom 猫对香肠非常感兴趣。
有一天, Tom 家里的女主人赏给了 Tom 一大堆香肠。这些香肠太多了,以至于 Tom 一顿吃不完,于是它把这些香肠串成了一棵树,树的每个节点上都有一个香肠。
Tom 需要给这些香肠进行编号,其中有 aaa 个香肠需要编号为 1,2,…,a1,2,\dots, a1,2,…,a 中的不重复的编号,作为早餐肠,剩下的 bbb 个香肠需要编号为 −1,−2,…,−b-1,-2,\dots,-b−1,−2,…,−b 中的不重复的编号,作为晚餐肠。
Tom 每天会随机吃一顿饭,可能是早饭,也可能是晚饭。如果是吃早饭, Tom 会吃掉编号绝对值最小的早餐肠,反之吃掉编号绝对值最小的晚餐肠。
如果一根香肠被吃掉了,那么与它相连的树上的边都会断掉,因此剩下的香肠可能会因此变成若干棵树,即变得不再连通。这是 Tom 不希望发生的事。
请给这些香肠编号,使得无论 Tom 如何安排早饭和晚饭,整棵树一直都是连通的。

Input

第一行三个正整数 n,a,bn, a, bn,a,b,代表节点的数目,早餐肠的数目,晚餐肠的数目。保证 a+b=na + b = na+b=n。
第二行开始,共 n−1n - 1n−1 行,每行两个正整数 u,vu, vu,v,代表树上一条边。

Output

共 nnn 行,第 iii 行输出第 iii 个节点的编号。
如果存在多种编号方式,请随意输出一种。如果不存在这样的编号方式,请输出 −1-1−1。

Sample Input

6 3 3
1 2
2 3
2 4
4 5
4 6

Sample Output

1 3 2 -3 -2 -1

Sample Explanation

编号后,无论如何安排早晚餐,香肠组成的树都是一直联通的。
另外,其它的编号方式也是可行的,比如 2,3,1,−3,−1,−22, 3, 1, -3, -1, -22,3,1,−3,−1,−2 等。

Hint

对于 30%30\%30% 的数据,n≤10n\le 10n≤10;
对于 40%40\%40% 的数据,n≤2000n\le 2000n≤2000;
对于另外 30%30\%30% 的数据,树是一条以 1,n1,n1,n 为端点的链;
对于另外 10%10\%10% 的数据,a=1a=1a=1;
对于全部的数据, n≤105,a+b=n,1≤a,bn\le 10^5, a+b=n, 1\le a,bn≤105,a+b=n,1≤a,b。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
const int N=200002;
int n,tot,A,B,head[N],nxt[N],adj[N],sz[N];
int xa,xb,tim,vis[N],val[N];
void add(int u,int v)
{
	tot++;
	nxt[tot]=head[u];
	head[u]=tot;
	adj[tot]=v;
}
void dfs(int u,int fa)
{
	sz[u]=1;
	for(int j=head[u];j;j=nxt[j])
		if(adj[j]!=fa)
		{
			dfs(adj[j],u);
			sz[u]+=sz[adj[j]];
			if(sz[adj[j]]==A)
			{
				xa=adj[j];
				xb=u;
			}
			if(sz[adj[j]]==B)
			{
				xb=adj[j];
				xa=u;
			}
		}
}
void DFS1(int i)
{
	val[i]=tim--;
	vis[i]=1;
	for(int j=head[i];j;j=nxt[j])
		if(!vis[adj[j]])
			DFS1(adj[j]);
}
void DFS2(int u)
{
	val[u]=tim++;
	vis[u]=1;int i;
	for(i=head[u];i;i=nxt[i])
		if(!vis[adj[i]])
			DFS2(adj[i]);
}
int main()
{
	int x,y,i;
	scanf("%d%d%d",&n,&A,&B);
	for(i=1;i<n;i++)
	{
		scanf("%d%d",&x,&y);
		add(x,y);add(y,x);
	}
	dfs(1,0);
	if(xa==0)
	{
		printf("-1");
		return 0;
	}
	vis[xa]=1;
	vis[xb]=1;
	tim=A;DFS1(xa);
	tim=-B;DFS2(xb);
	for(i=1;i<=n;i++)
		printf("%d ",val[i]);
	return 0;	
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值