链接:https://ac.nowcoder.com/acm/contest/51721/C
来源:牛客网
题目描述
小松鼠又开始研究树的基因了,他开发出了一种基因重组算法,能根据一些信息很快地还原一棵树,现在他想考考你!
给定一棵 nnn 个节点的有根树的 dfs 序以及每个点对应的子树大小,求这棵树。
保证有解哦!
输入描述:
输入共三行。第一行为节点数 n (2≤n≤106)n\ (2\leq n\leq 10^6)n (2≤n≤106),第二行为这棵树的 dfs 序,第三行为以 1∼n1\sim n1∼n 为根的每棵子树大小。
输出描述:
输出共 n−1n-1n−1 行。每行两个正整数表示 (u,v)(u,v)(u,v),要求 u<vu<vu<v 并且每行的 uuu 单调不降,对于相同的 uuu 所对应的 vvv 需要满足单调递增。
示例1
输入
4
1 2 4 3
4 2 1 1
输出
1 2
1 3
2 4
说明
树的形态如下图所示:
示例2
输入
3
3 1 2
1 1 3
输出
1 3
2 3
说明
第一次给出了dfs序即递归执行过程
所以我们只要在每次递归的过程中维护好父亲和儿子的关系就ok
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define YES cout<<"YES"<<endl
#define NO cout<<"NO"<<endl
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1e9+7;
const int INF=0x3f3f3f3f;
const int N = 1e6+10;
int d[N];int g[N];
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
int cnt=1;
vector<PII>p;
void dfs(int x)
{
g[x]--;
while(g[x])
{
int v=d[++cnt];
p.push_back({x,v});
g[x]-=g[v];
dfs(v);
}
}
void solve()
{
int n;cin>>n;
for(int i=1;i<=n;i++)
{
cin>>d[i];
}
for(int i=1;i<=n;i++)
{
cin>>g[i];
}
dfs(d[cnt]);
int len=p.size()-1;
for(int i=0;i<=len;i++)
{
auto [x,y]=p[i];
if(x>y)
{
swap(p[i].first,p[i].second);
}
}
sort(p.begin(),p.end());
for(auto [x,y] : p)
{
cout<<x<<" "<<y<<endl;
}
}
signed main()
{
int t;
t=1;
while(t--)
{
solve();
}
}