CF1510G Guide 题解

题意:给你一棵有 n 个节点的树,你需要累计到达 k 个节点,可以走回头路,不需要回到根节点。输出任意一条最短路径。
数据范围:1T100 组数据,每组数据 1kn100,保证 faii
尽管 n100,但是做法是 O(n) 的。因为从根节点出发而且不需要回到根节点,容易想到树上最长链。因为 k 个节点的限制,所以这个最长链的深度不能超过 k
因为只有那条链的路不得不走,所以剩下的路其实是可以随便走的。比较恶心的是输出路径,这题有个保证 faii,可以减少输出难度。对每个点开个 vis 数组,为 1 表示这个点在最终路径中。开始时把最长链上的所有 vis 设定为 1,从根节点开始 dfs,在跑的时候每新访问一个点就把剩余计数减一,如果剩余计数为 0 就没有必要访问其他点了。最长链上的点因为 faii 这个性质才能保证按照正确的顺序输出。
如果感觉不太懂可以看看代码的 dfs2 部分,code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cassert>
#define siz(x) int((x).size())
#define cauto const auto
#define all(x) (x).begin(),(x).end()
using std::cin;using std::cout;
using loli=long long;
using venti=__int128_t;
using pii=std::pair<int,int>;
constexpr int kN=101;
int n,m,k,cnt,fa[kN],dep[kN];
bool vis[kN];
std::basic_string<int>g[kN];
void dfs1(int u){
for(int v:g[u])if(v!=fa[u])
dep[v]=dep[u]+1,dfs1(v);
}
void dfs2(int u){
cout<<u<<' ';
for(int v:g[u])if(v!=fa[u]&&cnt&&!vis[v])
cnt--,dfs2(v),cout<<u<<' ';
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
std::ios::sync_with_stdio(false);cin.tie(nullptr);
int T;cin>>T;while(T--){
cin>>n>>k;m=1;
memset(vis+1,0,sizeof(bool)*n);
for(int i=1;i<=n;i++)g[i].clear();
for(int i=2;i<=n;i++)cin>>fa[i],g[fa[i]]+=i;
dep[1]=1;dfs1(1);
for(int i=2;i<=n;i++)if(dep[i]<=k&&dep[i]>dep[m])m=i;
cnt=k-dep[m];
cout<<(k-1)*2-dep[m]+1<<'\n';
while(m)vis[m]=true,m=fa[m];
for(int i=1;i<=n;i++)if(vis[i])dfs2(i);
cout<<'\n';
}
return 0;
}
posted @   蒟酱  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示