CF神奇构造题
题目大意
给出一颗 (N) 个节点树,每条边有边权,边权为 (0) 到 (N-2) 的整数,且不重复,使得任意两点的简单路径的MEX的最大值最小.(MEX指第一个没有出现过的非负整数)
分析
对于MEX最重要自然是 (0),而且因为是树,所以必然可以做到将 (0) 和 (1) 放入同一条树链中,那么就要考虑 (2) 的位置了,不可以让他出现在这条树链中,理解一下就是必须有一个点的度至少为 (3),即这个图不是一条链,那么就有一种非常容易的方法,将 (0,1,2) 放在三个度为 (1) 的点的边上,这样就不可能出现 (0,1,2) 同时出现在一条链上,其他也就可以乱放了,如果是一条链无论怎么放MEX都可以达到 (N-1),所以可以直接乱放.
代码
#include<bits/stdc++.h>
#define REP(i,first,last) for(int i=first;i<=last;++i)
#define DOW(i,first,last) for(int i=first;i>=last;--i)
using namespace std;
const int MAXN=114514;
int N,M;
int T;
int out[MAXN];//记录度
int p[MAXN];//比较懒,不想存图,所以就只记录一下每个点最后一条出边,反正最后有影响的之后度为1的点,所以没关系
int answer[MAXN];//记录答案
void work()
{
scanf("%d",&N);
int f,t;
REP(i,1,N-1)
{
scanf("%d%d",&f,&t);
out[f]++;
out[t]++;
p[f]=p[t]=i;
}
if(N==2)//注意特判2
{
printf("%d",0);
return;
}
int cnt=0;
REP(i,1,N)
{
if(out[i]==1)//在前三个度为1的点的出边赋值上0,1,2,为了方便处理这里就用了1,2,3
{
answer[p[i]]=++cnt;
if(cnt==3)
{
break;
}
}
}
REP(i,1,N-1)//输出
{
if(answer[i])//如果有答案就输出答案
{
printf("%d
",answer[i]-1);
}
else//没有反正可以乱输出
{
++cnt;
printf("%d
",cnt-1);
}
}
}
int main()
{
work();
return 0;
}