九度OJ 1359:大魏树遍历 (树)
- 题目描述:
-
大魏是JOBDU技术组里最喜欢折腾的一个了,单反、骑车、改九度页面,当然还有YY prado。我们姑且先把这些看做是会享受生活的表现;但是有一点我们就不能忍了,他连遍历树都有一些不一样的要求:1. 对于给定的一棵树,他要求从根节点开始遍历完所有节点,相对于一般的节点遍历,他要求边的遍历,即每条边都要正好遍历过两次2. 除了对于边遍历的变态要求,他还对叶子节点的遍历序列有着特殊的要求,即会预先指定所有叶子节点的遍历先后顺序。这些要求是不是很BT? 实际上也还好了,仔细想想也能做出来的。
- 输入:
-
每个测试文件包含多个测试案例,每个测试案例包含三个部分:第一行为一个整数K,代表这棵树总的节点个数, K>=1并且K<=300。接下来是K – 1行,每行有两个整数,代表这棵树的K – 1条边。树节点的标号从1开始,且1代表根节点。最后一行为包含所有的叶子节点编号的一个整数序列, 代表大魏所指定的叶子节点的遍历顺序。
- 输出:
-
对于每个测试案例,若满足大魏规定条件的遍历序列存在,则输出这个序列,每两个节点之间由空格隔开,末尾没有空格。若不存在,则只需要输出一个-1。
- 样例输入:
-
3 1 2 2 3 3 6 1 2 1 3 2 4 4 5 4 6 5 3 6
- 样例输出:
-
1 2 3 2 1 -1
代码:
#include <stdio.h> #include <string.h> #define N 301 int n,head[N],li[N],ri[N]; int e,nx[N-1],to[N-1]; int vti[N],mk[N],ln; int err,f1; int Tsort(int rt) { int l=N,r=-1,ct=0,eg,peg,sn,es,pes; if(head[rt]==0){ l=r=vti[rt]; ct=1; } else{ for(peg=0,eg=head[rt];eg;peg=eg,eg=nx[eg]){ sn=to[eg]; ct+=Tsort(sn); if(err) return 0; for(pes=0,es=head[rt];li[to[es]]<li[sn];pes=es,es=nx[es]) ; if(es!=eg){ nx[peg]=nx[eg]; nx[eg]=es; if(pes!=0) nx[pes]=eg; else head[rt]=eg; eg=peg; } if(li[sn]<l) l=li[sn]; if(ri[sn]>r) r=ri[sn]; } } if(r-l+1==ct){ li[rt]=l; ri[rt]=r; return ct; } else{ err=1; return 0; } } void printPT(int rt) { int eg; if(f1) printf("%d",rt),f1=0; else printf(" %d",rt); if(head[rt]!=0){ for(eg=head[rt];eg;eg=nx[eg]){ printPT(to[eg]); printf(" %d",rt); } } } int main() { int i,rt,sn,v; while(scanf("%d",&n)!=EOF){ err=0; e=1; ln=n; f1=1; memset(head,0,sizeof(head)); memset(mk,0,sizeof(mk)); mk[1]=1; for(i=0;i<n-1;i++){ scanf("%d%d",&rt,&sn); if(mk[sn]){v=sn;sn=rt;rt=v;} to[e]=sn; nx[e]=head[rt]; head[rt]=e++; if(mk[rt]==1) mk[rt]=2,ln--; mk[sn]=1; } for(i=1;i<=ln;i++){ scanf("%d",&v); vti[v]=i; } Tsort(1); if(err) printf("-1"); else printPT(1); printf("\n"); } return 0; } /************************************************************** Problem: 1359 User: lovai Language: C Result: Accepted Time:40 ms Memory:916 kb ****************************************************************/
编程算法爱好者。