• Tom


    题目描述

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

    输入格式

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

    输出格式

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

    样例输入1

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

    样例输出1

    1
    3
    2
    -3
    -2
    -1

    样例1 说明

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


    思路

    • 题目大意:一棵树只断掉一条边,剩下的两个连同快分别有a,b个节点
    • 注意:判断时要分别判断a,b;flag标记返回判断两次,否则会重复赋值

    代码

    #include <iostream>
    #include <cstdio>
    #define maxn 100005
    using namespace std;
    int n,a,b,head[maxn],cnt,siz[maxn],num[maxn],ka,kb,flag;
    struct fdfdfd{int next,to;}e[maxn<<1];
    void addedge(int x,int y){e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;}
    void dfs3(int x,int pre)
    {
    	num[x]=ka--;
    	for(int i=head[x];i;i=e[i].next)
    	{
    		int v=e[i].to;
    		if(v==pre) continue;
    		dfs3(v,x);
    	}
    }
    void dfs2(int x,int pre)
    {
    	num[x]=kb++;
    	for(int i=head[x];i;i=e[i].next)
    	{
    		int v=e[i].to;
    		if(v==pre) continue;
    		dfs2(v,x);
    	}
    }
    void dfs1(int x,int pre)
    {
    	if(flag) return;
    	siz[x]=1;
    	for(int i=head[x];i;i=e[i].next)
    	{
    		int v=e[i].to;
    		if(v==pre) continue;
    		dfs1(v,x);
    		if(flag) return;
    		siz[x]+=siz[v];
    	}
    	if(siz[x]==a) dfs3(x,pre),dfs2(pre,x),flag=1;
    	else if(siz[x]==b) dfs2(x,pre),dfs3(pre,x),flag=1;
    }
    int main()
    {
    	scanf("%d%d%d",&n,&a,&b); ka=a; kb=-b;
    	for(int i=1,u,v;i<n;++i) scanf("%d%d",&u,&v),addedge(u,v),addedge(v,u);
    	dfs1(1,0);
    	if(!flag) puts("-1");
    	else
    		for(int i=1;i<=n;++i) printf("%d ",num[i]);
    	return 0;
    }
    
  • 相关阅读:
    优先队列
    Problem W UVA 662 二十三 Fast Food
    UVA 607 二十二 Scheduling Lectures
    UVA 590 二十一 Always on the run
    UVA 442 二十 Matrix Chain Multiplication
    UVA 437 十九 The Tower of Babylon
    UVA 10254 十八 The Priest Mathematician
    UVA 10453 十七 Make Palindrome
    UVA 10163 十六 Storage Keepers
    UVA 1252 十五 Twenty Questions
  • 原文地址:https://www.cnblogs.com/wuwendongxi/p/13735424.html
Copyright © 2020-2023  润新知