/*
题意:一棵有根树,每个结点的权重为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]<<'\n';
for(int i=1;i<n;i++)
cout<<edge[i].first<<" "<<edge[i].second<<'\n';
}