题意:给你一颗n个点的树,用[0,n-2]去给n-1条边编号,使得mex(u,v)的最大值最小。
mex(u,v)表示任意两点的简单路径中不在这条边上的最小非负整数。
思路:
这个题目好巧妙啊~~~~哈哈哈哈,题目中给了一个很重要的信息被我忽略了,那就是它给出的是一棵树,意味着任意两点有且仅有一条简单路径,这个条件对构造结果很重要。首先我们考虑只要两个点的情况,那么这条边只能标记0,mex(u,v)也是0,因为取值只有0。(这是个坑需要特判掉)。考虑n<=4,你会发现无论你怎么构造都是一条链那么他的mex(u,v)最大值就是n-1。但是当n>=5的时候,只有存在一个顶点的度>=3那么那么mex(u,v)最大值只能是2.因为任意两条边只有一条路径(这个时候树的特点就出来的),因为你至少有一个度大于等于3意味着任意两条路径至少有一个点是是访问不到的,那么这个时候mex(u,v)最大值只能是2了。
问题就转化成了对于n>=5的情况找一个大于等于3的度的顶点给他的边标上0,1,2,然后其他的点随便标记。
构造题确实挺难的,场上一脸懵逼。。。。。不过这个构造确实巧妙~
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int g[maxn];
int main(){
int n;cin>>n;
pair<int,int>p[maxn];
for(int i = 1; i < n; i++){
cin>>p[i].first>>p[i].second;
g[p[i].first]++;
g[p[i].second]++;
}
if(n == 2){
cout<<"0"<<endl;return 0;
}
int k = 0;
for(int i = 1; i <= n; i++){
if(g[i]>=3) k =i;
}
int l = 0,r = n-2;
for(int i = 1; i < n; i++){
if(p[i].first == k ||p[i].second == k){
cout<<l<<endl;l++;
}else{
cout<<r<<endl;r--;
}
}
}