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

posted @ 2023-07-17 21:40  HQJ2007  阅读(48)  评论(0)    收藏  举报