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;
}