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;
}
posted @ 2026-07-18 23:23  yushihan  阅读(4)  评论(0)    收藏  举报