CF765E Tree Folding
题意
给出一颗无根树,你可以钦定一个根,并进行若干次下述操作:
- 选择一个点
,以及 延伸出去的两条长度相同的路径(两条路径没有重叠的边)。删去其中任意一条(不删 )。
现在,操作次数、
解题思路
任取一个根,进行一遍
但问题在于如何把节点
合并完后,我们进行一个分类讨论:
-
有
种不同的链长证明这个节点是叶节点,返回
。 -
只有
种链长(设它为 )子树合并后的链长为
。 -
有两种不同的链长
-
当前节点不是根节点
会发现在当前的树最后不可能变成一条链,同时记录一个
, 。 -
当前节点为根节点
形成了一条链,返回两种链长相加。
-
-
有
种不同的链长最终不可能变成一条链。
这样的策略是在钦定了一个根的情况下。假设通过上述流程,最终没法变成一条链,考虑把
点击查看代码
#include <bits/stdc++.h>
#define FL(i, a, b) for(int i = (a); i <= (b); i++)
#define FR(i, a, b) for(int i = (a); i >= (b); i--)
using namespace std;
const int N = 2e5 + 10;
unordered_map<int, int> mp[N];
int n, r, ans, rt = 1;
vector<int> e[N];
int dfs(int u, int p){
unordered_map<int, int>().swap(mp[u]);
for(int &v: e[u]) if(v != p){
mp[u][r = dfs(v, u) + 1] = 1;
if(!r) return -1;
}
if(!mp[u].size()) return 0;
if(mp[u].size() <= 1 + (!p)){
r = 0; for(auto &it: mp[u]) r += it.first;
return r;
}
rt = u; return -1;
}
int main(){
scanf("%d", &n);
FL(i, 2, n){
int u, v; scanf("%d%d", &u, &v);
e[u].emplace_back(v), e[v].emplace_back(u);
}
dfs(1, 0), ans = dfs(rt, 0);
printf("%d\n", ans >> __builtin_ctz(ans));
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现