题目链接
Luogu方向
Atcoder方向
题目解法
手玩几个小数据之后可以猜测最小的最大相似度一定为1
考虑构造:每次找到2个叶子,交换权值,然后删掉(最后如果剩下一个点权值不变)
证明:
首先可以证明最大的相似度一定
>
=
1
>=1
>=1
首先可以知道最大相似度一定是在极长的路径中(即无法再扩充的路径)
考虑
u
,
v
u,v
u,v 之间的路径
- 路径中没有
2
2
2 个点匹配
那么每个点(可能除了根)一定和路径外的点匹配且交换了权值,那么这条路径中一定没有点的权值(可能除了根)与路径上其他点的编号相同,所以相似度最多为 1 1 1(即根无法匹配) - 路径中有 2 2 2 个点匹配
令在
u
−
l
c
a
u-lca
u−lca 的路径上匹配的点为
x
x
x,在
v
−
l
c
a
v-lca
v−lca 的路径上匹配的点为
y
y
y
可以证明
x
,
y
x,y
x,y 一定不同时在
u
−
l
c
a
u-lca
u−lca 或
v
−
l
c
a
v-lca
v−lca 的路径上,因为父亲一定比儿子晚删
所以可以有这样一张图:
考虑在
u
−
x
u-x
u−x 上的点
p
p
p,它匹配的点
q
q
q 有2种情况
3.
q
q
q 在
u
−
v
u-v
u−v 的路径上,那么
q
q
q 一定在
v
−
y
v-y
v−y 上
如果在
y
−
l
c
a
y-lca
y−lca 上,那么
p
p
p 比
x
x
x 早删,
q
q
q 比
y
y
y 晚删,
x
,
y
x,y
x,y 同时删,矛盾
4.
q
q
q 不在
u
−
v
u-v
u−v 的路径上,不用考虑,没有影响
所以说
u
−
v
u-v
u−v 的路径是类似关于
l
c
a
lca
lca 对称的
u
−
l
c
a
u-lca
u−lca 的从下到上的点在
v
−
l
c
a
v-lca
v−lca 上的对应点也是从下到上的
v
−
l
c
a
v-lca
v−lca 的同理
所以该构造最小的最大相似度为1
#include <bits/stdc++.h>
using namespace std;
const int N(5100);
int n,deg[N],val[N];
int que[N],hh,tt=-1;
int e[N<<1],ne[N<<1],h[N],idx;
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++;}
int main(){
n=read();
memset(h,-1,sizeof(h));
for(int i=1,x,y;i<n;i++) x=read(),y=read(),add(x,y),add(y,x),deg[x]++,deg[y]++;
for(int i=1;i<=n;i++) if(deg[i]==1) que[++tt]=i;
while(hh<=tt){
// cout<<hh<<' '<<tt<<' '<<que[hh]<<'\n';
if(hh==tt){ val[que[hh]]=que[hh];break;}
int u=que[hh++],v=que[hh++];
val[u]=v,val[v]=u;
for(int i=h[u];~i;i=ne[i]){
deg[e[i]]--;
if(deg[e[i]]==1) que[++tt]=e[i];
}
for(int i=h[v];~i;i=ne[i]){
deg[e[i]]--;
if(deg[e[i]]==1) que[++tt]=e[i];
}
}
for(int i=1;i<=n;i++) printf("%d ",val[i]);
return 0;
}