P5022 旅行 题解

博客园同步

原题链接

简要题意:

给定一棵树(或基环树),每个节点只能至多回溯一次,求遍历整棵树的最小字典序。

基环树概念:树多一条边,即树上出现且仅出现一个环。

作为 NOIP2018   Day2   T1 \texttt{NOIP2018 Day2 T1} NOIP2018 Day2 T1,确实有些难度。不过我们从部分分开始想。

对于 60 % 60 \% 60% 的数据,给定的是树。

那么就有这样的性质:

  • 1 1 1 为根,并从 1 1 1 开始遍历肯定是最优的。(因为 1 1 1 的字典序最小)

  • 假设 u u u 的父亲节点是 v v v,那么 u u u 想要回溯到 v v v 的条件应该是 u u u 的所有子树已经遍历完毕。因为如果没有遍历完就回溯到 v v v,后面不可能有其它边伸向这个子树。(当然除非是基环树)

根据上面两条性质,我们草稿一些程序步骤:

  1. 对于当前节点,按照其儿子的大小进行遍历。即 先遍历第 1 1 1 小,然后第 2 2 2 ⋯ ⋯ \cdots \cdots

  2. 当前是叶子节点,那么就结束,回溯到第 1 1 1 步。

最后统计答案即可,其实就是一个 dfs \text{dfs} dfs 遍历树的变版。

时间复杂度: O ( n + m ) O(n+m) O(n+m).

实际得分: 60 p t s 60pts 60pts.

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;

const int N=5e3+1;

inline int read(){
   char ch=getchar();int f=1;while(ch<'0' || ch>'9') {
   if(ch=='-') f=-f; ch=getchar();}
	int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}

int n,m,fa[N]; //fa[i] 表示 i 的父亲节点
vector<int>G[N]; //图
vector<int>son[N]; //儿子节点

inline void dfs_fa(int dep,int bs) {
    //表示 bs 是 dep 的父亲
//	printf("%d %d\n",dep,bs);
	fa
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值