大意:
给你一棵树,已知根节点为1.
令Si表示以节点i为根的子树
每一个节点会有两个数l,r(l<=r),所有数的构建应当满足
现在求一种构建方式,使所出现的数尽可能小。
输出每一个点对应的l,r
思路:
对于每一个叶节点,要让总的数尽可能小,那么叶节点的l=r自然是最优的。我们一次dfs找出所有叶节点并计数,每一个叶节点的l,r就是它对应的计数编号。
然后再来一次dfs从根往下递归,每一个根节点的l应该使它的所有叶节点的l的最小值,相应的,根节点的r就应该是所有叶节点的r的最大值。
两次dfs即可解决问题
#include<bits/stdc++.h>
using namespace std;
#define ll long long
vector<ll> mas[200010];
ll a,b;
ll lf[200010];
ll cnt=0;//叶子数
ll l[200010];
ll r[200010];
void dfs(ll u,ll p){
if(u!=1&&mas[u].size()==1){
lf[u]=++cnt;
return;
}
for(ll i:mas[u]){
if(i!=p){
dfs(i,u);
}
}
return;
} //建树
void dfs2(ll u,ll p){
if(lf[u]){
l[u]=lf[u];
r[u]=lf[u];
return;
}
l[u]=1e9,r[u]=-1e9;
for(ll i:mas[u]){
if(i==p) continue;
dfs2(i,u);
l[u]=min(l[u],l[i]);
r[u]=max(r[u],r[i]);
}
}
int main()
{//1是根节点
int n;
cin>>n;
for(int i=1;i<n;++i){
cin>>a>>b;
mas[a].push_back(b);
mas[b].push_back(a);
}
dfs(1,-1);
dfs2(1,-1);
for(int i=1;i<=n;++i){
cout<<l[i]<<" "<<r[i]<<endl;
}
return 0;
}