/* 题意:一棵有根树,每个结点的权重为2^i,每条边的权重为其下子树结点的权重和 现在按边权降序排序,每条边记录高度大的那个点,得到一个长度为n-1的序列 根据这个序列构造出一棵合法的树 性质:(fa[fa[u]],fa[u])必排在(fa[u],u)前面 可以自底向上构造这棵树,先把叶子结点放进set里,然后倒序遍历数列,每次取出一个叶子结点到它的父节点里去,同时更新父亲结点的权值 如果父节点下的结点都被塞进去了,那么把这个父亲结点放进set,整个过程有点像拓扑排序 */ #include<bits/stdc++.h> using namespace std; #define N 200005 int n,a[N],son[N],Max[N]; set<pair<int,int> >s; set<pair<int,int> >::iterator it; pair<int,int>edge[N]; int main(){ cin>>n; for(int i=1;i<n;i++)cin>>a[i],son[a[i]]++; for(int i=1;i<=n;i++)Max[i]=i; for(int i=1;i<=n;i++)if(!son[i])s.insert(make_pair(Max[i],i)); for(int i=n-1;i>=1;i--){ it=s.begin(); edge[i].first=a[i]; edge[i].second=(*it).second; son[a[i]]--; Max[a[i]]=max(Max[(*it).second],Max[a[i]]); if(son[a[i]]==0) s.insert(make_pair(Max[a[i]],a[i])); s.erase(it); } cout<<a[1]<<' '; for(int i=1;i<n;i++) cout<<edge[i].first<<" "<<edge[i].second<<' '; }