CF1325C题解(奇怪思路)
首先我们可以发现如果这棵树是一个链的话,mex(u,v)的最大值的最小值,一定是n-1,所以这种情况随便乱放就可以。
然后考虑不是链的情况,我们可以发现如果从u到v之间路径的长度>=2的话一定有路径包含1和0(因为树是没有环的),那么如果要最小化mex(u,v)的最大值,就必须让2不出现在这个路径里(这三个数哪一个不出现在路径里都可以,因为要求的是mex(u,v)的最大值的最小值)。所以mex(u,v)最大值的最小值一定是1或2。
我们再观察一下,可以发现只需要找到最长的路径(树的直径),然后把不在路径上的点赋值为0,1,2中的一个值,再把剩下的两个数分别放在这个点的上半部分和下半部分,其余的随便放,这个问题就解决了。
当然,这道题可以直接找度数>=3的点,wtcl,显然没有想到这么简单的方法,写了一堆奇奇怪怪的东西。
代码如下:
附赠代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=1e5+5;
int e[N*2],ne[N*2],h[N],idx;
int dist[N],vis[N],a[N],b[N],d;
bool f[N],flag;
PII p1[5],p2[5];
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int fa,int len){
dist[u]=len;
for(int i=h[u];~i;i=ne[i]){
int v=e[i];
if(v==fa) continue;
if(len+1>dist[v]) vis[v]=u;
dfs(v,u,len+1);
}
}
void dfs1(int u,int fa){
if(flag) return;
int cnt=0;
for(int i=h[u];~i;i=ne[i]){
int v=e[i];
if(v==fa||v==d) continue;
cnt++;
}
if(cnt>=2){
int c=1;
for(int i=h[u];~i;i=ne[i]){
int v=e[i];
if(v==fa||v==d) continue;
p1[c]={v,u};
p2[c]={u,v};
c++;
if(c>2) break;
}
flag=1;
return;
}
for(int i=h[u];~i;i=ne[i]){
int v=e[i];
if(v==fa) continue;
dfs1(v,u);
}
}
int main(){
int n;
scanf("%d",&n);
memset(h,-1,sizeof h);
for(int i=1;i<n;i++){
scanf("%d%d",&a[i],&b[i]);
add(a[i],b[i]);
add(b[i],a[i]);
}
memset(dist,-0x3f,sizeof dist);
dfs(1,0,0);
int mx=0,l=0,r=0;
for(int i=1;i<=n;i++){
if(dist[i]>mx){
mx=dist[i];
l=i;
}
}
memset(dist,-0x3f,sizeof dist);
dfs(l,0,0);
mx=0;
for(int i=1;i<=n;i++){
if(dist[i]>mx){
mx=dist[i];
r=i;
}
}
if(mx==n-1){
for(int i=0;i<n-1;i++){
printf("%d\n",i);
}
return 0;
}
for(int i=r;i!=l;i=vis[i]){
f[i]=1;
}
int k=0;
for(int i=1;i<=n;i++){
if(!f[i]){
k=i;
break;
}
}
p1[0]={k,e[h[k]]};
p2[0]={e[h[k]],k};
d=e[h[k]];
dfs1(k,0);
int cnt=3;
for(int i=1;i<n;i++){
int ff=0;
for(int p=0;p<=2;p++){
if(p1[p].first==a[i]&&p1[p].second==b[i]||p2[p].first==a[i]&&p2[p].second==b[i]){
printf("%d\n",p);
ff=1;
break;
}
}
if(!ff){
printf("%d\n",cnt);
cnt++;
}
}
return 0;
}

浙公网安备 33010602011771号