题目描述
小 Y 是一个心灵手巧的 OIer,她有许多二叉树模型。
小 Y 的二叉树模型中,每个结点都具有一个编号,小 Y 把她最喜欢的一个二叉树模型挂在了墙上,树根在最上面,左右子树分别在树根的左下方与右下方,且他们也都满足这样的悬挂规则。为了让这个模型更加美观,小 Y 选择了一种让这棵二叉树的中序遍历序列最小的悬挂方法。所谓中序遍历最小,就是指中序遍历的结点编号序列的字典序最小。
一天,这个模型不小心被掉在了地上,幸运的是,所有结点和边都没摔坏,但是她想不起这个模型原来是怎么悬挂的了,也就是说:她想不起来树根节点的编号了。
小 Y 最近忙于准备清华集训,所以没太多时间处理别的事情,她只好找到同样心灵手巧的你帮忙复原她的二叉树模型。
输入输出格式
输入格式:
从文件 binary.in 中读入数据。
第一行为一个正整数 n ,表示点的个数。
后接 n 行,每行若干个整数:
第 i + 1 行的第一个整数为 ki ,表示编号为 i 的结点的度数,后接 ki 个整数 ai; j ,表示编号为 i 的结点与编号为 ai; j 的结点之间有一条边。
同一行输入的相邻两个元素之间,用恰好一个空格隔开。
输出格式:
输出到文件 binary.out 中。
输出共一行, n 个整数,表示字典序最小的中序遍历。
题意:给一颗二叉树,你可以随意选择根节点和随意改变儿子顺序,求字典序最小的中序遍历;
题解:
①不断构造;
②假定选好了根节点。mn[v]表示,v的子树中开头的最小值,(根除外)一个结点的度数小于等于2,一个节点可以开头。这样从根不断向下找mn小的做左儿子贪心可以构造出序列;
③现在找根节点,首先最左面的节点一定是固定的,为度数小于等于2的最小值;从这个点u不断往上找,预处理以u为根的所有mn[],然后u对有一个儿子的情况,那么mn较小的应该是u的右儿子,mn较大的应该是u的父亲,只有一个儿子v,mn[v]小于v,那么在真正的结构里v应该是u的右儿子,否则v是u的父亲;不断递归u向上找即可;
④最后再dfs一次输出答案;
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 const int N=1000010; 5 int n,m,d[N],rt,st,o,hd[N],ls[N],rs[N],son[N][2],mn[N]; 6 struct Edge{int v,nt;}E[2*N]; 7 char gc(){ 8 static char *p1,*p2,s[10000000]; 9 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 10 return(p1==p2)?EOF:*p1++; 11 } 12 int rd(){ 13 int x=0; char c=gc(); 14 while(c<'0'||c>'9') c=gc(); 15 while(c>='0'&&c<='9') x=x*10+c-'0',c=gc(); 16 return x; 17 } 18 void adde(int u,int v){E[o]=(Edge){v,hd[u]};hd[u]=o++;}// 19 void dfsA(int u,int fa){ 20 int cnt=0; 21 for(int i=hd[u],v;i!=-1;i=E[i].nt){ 22 if((v=E[i].v)==fa) continue; 23 son[u][cnt++]=v; 24 dfsA(v,u); 25 mn[u] = min(mn[v],mn[u]); 26 } 27 }// 28 void find(int u){ 29 if(d[u]==1&&u!=st) {rt=u;return;} 30 else if(u!=st&&d[u]==2||d[u]==1&&u==st){ 31 if(son[u][0]<mn[son[u][0]]) find(son[u][0]); 32 else {rt=u; return;} 33 } 34 else{ 35 if(mn[son[u][0]]>mn[son[u][1]]) find(son[u][0]); 36 else find(son[u][1]); 37 } 38 }// 39 int dfsB(int u,int fa){ 40 if(d[u]==1&&u!=rt) return u; 41 int tmp=n+1; if(u!=rt&&d[u]==2||u==rt&&d[u]==1) tmp=u; 42 for(int i=hd[u],v,now;i!=-1;i=E[i].nt){ 43 if((v=E[i].v)==fa) continue; 44 if((now=dfsB(v,u))<tmp) rs[u]=ls[u],ls[u]=v,tmp=now; 45 else rs[u]=v; 46 } 47 return tmp; 48 }// 49 void dfsC(int u){ 50 if(ls[u]) dfsC(ls[u]); 51 printf("%d ",u); 52 if(rs[u]) dfsC(rs[u]); 53 } 54 int main() 55 { freopen("mzoj1120.in","r",stdin); 56 freopen("mzoj1120.out","w",stdout); 57 n=rd(); 58 for(int i=1;i<=n;i++){ 59 hd[i]=-1;d[i]=rd(); 60 for(int j=1;j<=d[i];j++) adde(i,rd()); 61 if(d[i]<=2) {mn[i]=i; if(!st)st=i;} else mn[i]=n+1; 62 } 63 //d[st]++; 64 dfsA(st,0); 65 find(st); 66 dfsB(rt,0); 67 dfsC(rt); 68 return 0; 69 }//by tkys_Austin;