题解 CF1338B Edge Weight Assignment
小清新思维题。
先找一个不是叶子的节点,令它为根。
那么当且仅当,对于每一个非叶子节点,它包含的叶子节点到它的异或路径相等时,才满足题目要求。
考虑第一问,显然如果每个叶子的深度奇偶性相同,可以全填一样的数字,答案为 \(1\)。反之为 \(3\)(可以在一条链上试一试)。
对于第二问,定义 \(f_i\) 表示子树 \(i\) 最多能填多少种边权,转移方程如下。
\[f_{i}=\left(\sum\limits_{j\in \operatorname{son}(i)\land j\notin leaves}f_j+1\right)+[\exists j\in\operatorname{son}(i),j\in leaves]
\]
简单理解就是,如果儿子中有叶子,那么每个叶子所连边的权值相等,其他的随便填。
复杂度 \(O(n)\)。
code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,dep[N],f[N],lv[N];
vector<int>adj[N];
void dfs(int u,int lst){
dep[u]=dep[lst]+1;
if(lv[u])return;
bool fg=0;
for(int i=0;i<adj[u].size();++i){
int v=adj[u][i];if(v==lst)continue;
dfs(v,u);
if(lv[v])fg=1;
else f[u]+=f[v]+1;
}
f[u]+=fg;
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<n;++i){
int u,v;cin>>u>>v;
adj[u].push_back(v);adj[v].push_back(u);
}
int rt;
for(int i=1;i<=n;++i){
if(adj[i].size()==1)lv[i]=1;
else rt=i;
}
dep[0]=-1;
dfs(rt,0);
int cnt=0,cnt2=0;
for(int i=1;i<=n;++i){
if(adj[i].size()>1)continue;
if(dep[i]&1)++cnt;
else ++cnt2;
}
if(cnt&&cnt2)cout<<3<<" ";
else cout<<1<<" ";
cout<<f[rt]<<endl;
return 0;
}

浙公网安备 33010602011771号