[CF1338B] Edge Weight Assignment

Description

给定一棵 $ n $ 个点的无根树,要求给每条边分配一个正整数权值,使得任意两个叶子节点之间路径上的边权异或值为 $ 0 $。求最少要多少种不同权值,以及最多可以使用多少种不同权值。
这里,填入的边权值可以为任意大。
$ 3 le nle 10^5 $

Solution

考虑最小值,如果存在两个叶子之间的距离为奇数,则答案为 (3)(没有连接叶节点的边上交替填 (1,2),部分叶子边可能填 (3)),否则答案为 (1)

考虑最大值,将每个结点的叶子结点合并为一个结点后,计算树边的总数

#include <bits/stdc++.h>
using namespace std;

#define int long long
#define dis dep
const int N = 1000005;
int n,vis[N],dep[N],f[N],ans;
vector <int> g[N],leaf;

void dfs1(int p) {
    vis[p]=1;
    for(int q:g[p]) if(vis[q]==0) {
        dep[q]=dep[p]+1;
        if(g[q].size()==1) ++f[p];
        dfs1(q);
    }
    if(f[p]) ans-=f[p]-1;
}


signed main() {
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<n;i++) {
        int t1,t2;
        cin>>t1>>t2;
        g[t1].push_back(t2);
        g[t2].push_back(t1);
    }
    int r=0;
    for(int i=1;i<=n;i++) if(g[i].size()==1) leaf.push_back(i); else r=i;
    dep[r]=0;
    dfs1(r);
    vector <int> leafdis;
    for(int i:leaf) leafdis.push_back(dis[i]&1);
    if(*min_element(leafdis.begin(),leafdis.end()) == *max_element(leafdis.begin(),leafdis.end())) {
        cout<<1<<" ";
    }
    else {
        cout<<3<<" ";
    }
    cout<<ans+n-1;
}
原文地址:https://www.cnblogs.com/mollnn/p/12812700.html