zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Flex Cairngorm简介
    caringorm3学习
    实现自动间休[原创]
    vs2003/vs2005快捷键使用大全(转帖)
    美国流行口语26句
    日记 [2007年08月29日]
    一个博客的排版问题,郁闷中
    你真的懂我吗?<谈谈接口>
    教你如何辨别手机是行货还是水货
    五十音图速记法
  • 原文地址:https://www.cnblogs.com/wuwendongxi/p/13735424.html
Copyright © 2011-2022 走看看