NOIP2018提高组day2 - T1:旅行

news2024/11/27 2:02:29

题目链接

[NOIP2018 提高组] 旅行

题目描述

小 Y 是一个爱好旅行的 OIer。她来到 X 国,打算将各个城市都玩一遍。

小 Y 了解到,X 国的 n n n 个城市之间有 m m m 条双向道路。每条双向道路连接两个城市。 不存在两条连接同一对城市的道路,也不存在一条连接一个城市和它本身的道路。并且, 从任意一个城市出发,通过这些道路都可以到达任意一个其他城市。小 Y 只能通过这些 道路从一个城市前往另一个城市。

小 Y 的旅行方案是这样的:任意选定一个城市作为起点,然后从起点开始,每次可 以选择一条与当前城市相连的道路,走向一个没有去过的城市,或者沿着第一次访问该 城市时经过的道路后退到上一个城市。当小 Y 回到起点时,她可以选择结束这次旅行或 继续旅行。需要注意的是,小 Y 要求在旅行方案中,每个城市都被访问到。

为了让自己的旅行更有意义,小 Y 决定在每到达一个新的城市(包括起点)时,将它的编号记录下来。她知道这样会形成一个长度为 n n n 的序列。她希望这个序列的字典序 最小,你能帮帮她吗? 对于两个长度均为 n n n 的序列 A A A B B B,当且仅当存在一个正整数 x x x,满足以下条件时, 我们说序列 A A A 的字典序小于 B B B

  • 对于任意正整数 1 ≤ i < x 1 ≤ i < x 1i<x,序列 A A A 的第 i i i 个元素 A i A_i Ai 和序列 B B B 的第 i i i 个元素 B i B_i Bi 相同。
  • 序列 A A A 的第 x x x 个元素的值小于序列 B B B 的第 x x x 个元素的值。

输入格式

输入文件共 m + 1 m + 1 m+1 行。第一行包含两个整数 n , m ( m ≤ n ) n,m(m ≤ n) n,m(mn),中间用一个空格分隔。

接下来 m 行,每行包含两个整数 u , v ( 1 ≤ u , v ≤ n ) u,v (1 ≤ u,v ≤ n) u,v(1u,vn) ,表示编号为 u u u v v v 的城市之 间有一条道路,两个整数之间用一个空格分隔。

输出格式

输出文件包含一行, n n n 个整数,表示字典序最小的序列。相邻两个整数之间用一个 空格分隔。

样例 #1

样例输入 #1

6 5 
1 3 
2 3 
2 5 
3 4 
4 6

样例输出 #1

1 3 2 5 4 6

样例 #2

样例输入 #2

6 6 
1 3 
2 3 
2 5 
3 4 
4 5 
4 6

样例输出 #2

1 3 2 4 5 6

提示

【数据规模与约定】

对于 100 % 100\% 100% 的数据和所有样例, 1 ≤ n ≤ 5000 1\le n \le 5000 1n5000 m = n − 1 m = n − 1 m=n1 m = n m = n m=n

对于不同的测试点, 我们约定数据的规模如下:

在这里插入图片描述

算法思想

根据题目描述:

  • 任意选定一个城市作为起点,然后从起点开始,每次可以选择一条与当前城市相连的道路,走向一个没有去过的城市,或者沿着第一次访问该 城市时经过的道路后退到上一个城市
  • 在旅行方案中,每个城市都被访问到

访问过程的就是一个DFS序列,要求的其中字典序最小的序列。

从数据范围来看,有 m = n − 1 m = n − 1 m=n1 m = n m = n m=n两种情况,由于从任意一个城市出发,通过这些道路都可以到达任意一个其他城市,也就是说:

  • m = n − 1 m = n − 1 m=n1 时,城市与道路构成一棵树
  • m = n m = n m=n时,就是在树上在加一条边,构成基环树,也叫环套树,是一种有 n n n个点 n n n条边的图。

树的深度优先遍历

先处理 m = n − 1 m = n - 1 m=n1的情况,即对一棵树进行DFS。为了得到字典序最小的DFS序列,就必须从 1 1 1号点开始遍历,每次按编号从小到大的顺序遍历所有子节点。

时间复杂度

DFS遍历树的时间复杂度为 O ( n + m ) O(n+m) O(n+m)

代码实现(60分)

#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 5005;
vector<int> g[N];
vector<int> ans(N, N); //答案序列全部初始化为N
int cnt = 0;
bool st[N];
int n, m;
void dfs(int u)
{
    st[u] = 1;
    ans[cnt ++] = u;
    for(int v : g[u]) //遍历子结点
    {
        if(st[v]) continue;
        dfs(v);
    }
}
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 0; i < m; i ++)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        g[a].push_back(b), g[b].push_back(a); //连接a和b的双向边
    }
    //对每个节点的子节点按编号从小到大排序
    for(int i = 1; i <= n; i ++) sort(g[i].begin(), g[i].end());
    dfs(1);
    for(int i = 0; i < n; i ++) cout << ans[i] << " ";
    return 0;
}

基环树

在上述实现中,只会遍历 n n n个点和与其相邻的的 n − 1 n−1 n1条边。当 m = n m = n m=n时,就是在树上在加一条边,即树中有一个环,构成基环树。那是否要先把环找出来再处理呢?

从数据范围来看, 1 ≤ n ≤ 5000 1\le n \le 5000 1n5000 n n n比较小,可以枚举一条构成环的边,将其删除;然后DFS求出最小字典序即可。

在DFS过程中,通过维护当前序列和最优序列的大小关系可以进行最优性剪枝。如果当前序列的字典序一定大于最优序列,则直接退出。

时间复杂度

  • 枚举边的时间复杂度为 O ( m ) O(m) O(m)
  • DFS遍历树的时间复杂度为 O ( n + m ) O(n + m) O(n+m)

总的时间复杂度为 O ( n 2 ) O(n^2) O(n2)

代码实现(100分)

#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
typedef pair<int, int> PII;
const int N = 5005;
vector<int> g[N];
vector<int> ans(N, N); //答案序列,全部初始化为N
vector<int> cur(N); //存储当前搜索序列
int cnt, cmp; 
bool st[N];
int n, m, du, dv;
vector<PII> e;
void dfs(int u)
{
    if(cmp == 0) //当前序列和答案序列相等
    {
        if(u < ans[cnt]) cmp = -1; //当前序列字典序更小,继续搜索
        if(u > ans[cnt]) { cmp = 1; return ; } //当前序列字典序更大,剪枝
    }
    st[u] = 1; //标记已访问
    cur[cnt ++] = u; //存储访问的城市编号
    for(int v : g[u]) //遍历子结点
    {
        if(st[v] || (u == du && v == dv) || (u == dv && v == du)) continue;
        dfs(v);
    }
}
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 0; i < m; i ++)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        g[a].push_back(b), g[b].push_back(a); //连接a和b的双向边
        e.push_back({a, b}); //存边
    }
    //对每个节点的子节点按编号从小到大排序
    for(int i = 1; i <= n; i ++) sort(g[i].begin(), g[i].end());
    if(m == n - 1) 
    {
        dfs(1);
        ans = cur;
    }
    else
    {
        for(int i = 0; i < m; i ++) //枚举要删除的边
        {
            du = e[i].first, dv = e[i].second;
            //cmp用来比较搜索序列和答案序列的字典序,初始为0表示相等
            cnt = cmp = 0;
            memset(st, 0, sizeof st);
            dfs(1);
            if(cnt == n && cmp < 0) //遍历完所有的点,并且搜索序列的字典序更小
                ans = cur;
        }
    }
    for(int i = 0; i < n; i ++) cout << ans[i] << " ";
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1393132.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

跨站点请求伪造攻击 - Cross Site Request Forgery (CSRF)

什么是CSRF 最好理解CSRF攻击的方式是看一个具体的例子。 假设你的银行网站提供一个表单,允许当前登录用户将钱转账到另一个银行账户。例如,转账表单可能如下所示: <form method="post"action="/transfer"> <

【深度强化学习】目前落地的挑战与前沿对策

到目前为止&#xff0c;深度强化学习最成功、最有名的应用仍然是 Atari 游戏、围棋游戏等。即使深度强化学习有很多现实中的应用&#xff0c;但其中成功的应用并不多。为什么呢&#xff1f;本文总结目前的挑战。 目录 所需的样本数量太大探索阶段代价太大超参数的影响非常大稳定…

【机器学习】机器学习四大类第01课

一、机器学习四大类 有监督学习 (Supervised Learning) 有监督学习是通过已知的输入-输出对&#xff08;即标记过的训练数据&#xff09;来学习函数关系的过程。在训练阶段&#xff0c;模型会根据这些示例调整参数以尽可能准确地预测新的、未见过的数据点的输出。 实例&#x…

【软件测试学习笔记6】Linux常用命令

格式 command [-options] [parameter] command 表示的是命令的名称 []表示是可选的&#xff0c;可有可无 [-options]&#xff1a;表示的是命令的选项&#xff0c;可有一个或多个&#xff0c;也可以没有 [parameter]&#xff1a;表示命令的参数&#xff0c;可以有一个或多…

Vue3在点击菜单切换路由时,将ElementPlus UI库中el-main组件的内容滚动恢复到顶部

功能&#xff1a;Vue3在点击菜单切换路由时&#xff0c;将页面el-main的内容滚动到顶部&#xff0c;布局如下&#xff0c;使用UI组件库为ElementPlus 在网上搜很多都是在route.js中的router.beforeEach中使用window.scrollTop(0,0) 或 window.scrollTo(0,0) 滚动&#xff0c;但…

【用法总结】LiveData组件要点

【用法总结】LiveData组件要点 1、如何实现和生命周期的关联&#xff1f;1.1 observe的实现逻辑&#xff1a;1.2 观察者的装饰者&#xff1a;ObserverWrapper1.3 观察者集合的存储&#xff1a;SafeIterableMap<Observer<? super T>, ObserverWrapper>&#xff0c;…

ChatGPT 商业提示词攻略书

原文&#xff1a;ChatGPT Business Prompt Playbook 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 一、书系介绍 人工智能发展迅速。非常迅速。 所以我希望你做两件事&#xff1a; (1) 在 Twitter 上关注我&#xff1a;iamkylebalmer (2) 订阅我的免费电子邮件通…

springcloud Client端cloud-consumer-order80

文章目录 简介建立module修改pom修改yml主启动类把公共代码写在一个mudule 里面测试 简介 这个是和之前的8001相互配合端口测试 这里的80的用户测试端口。 代码在&#xff1a;GitHub 上&#xff1a;https://github.com/13thm/study_springcloud/tree/main/days2 建立module …

小程序 自定义组件和生命周期

文章目录 ⾃定义组件创建⾃定义组件声明组件编辑组件注册组件 声明引⼊⾃定义组件⻚⾯中使⽤⾃定义组件定义段与⽰例⽅法组件-⾃定义组件传参过程 小程序生命周期应用生命周期页面生命周期页面生命周期 ⾃定义组件 类似vue或者react中的自定义组件 ⼩程序允许我们使⽤⾃定义组件…

1.C语言基础知识

这里写目录标题 1.第一个C语言程序2.注释3.标识符4.关键字5.数据类型6.变量7.常量8.运算符9.输入输出输入输出 1.第一个C语言程序 C语言的编程框架 #include <stdio.h> int main() {/* 我的第一个 C 程序 */printf("Hello, World! \n");return 0; }2.注释 单行…

RHCE9学习指南 第21章 用bash写脚本

grep的用法是&#xff1a; grep 关键字 file 意思是从file中过滤出含有关键字的行。 例如&#xff0c;grep root /var/log/messages&#xff0c;意思是从/var/log/messages中过滤出含有root的行。这里很明确的是过滤含有“root”的行。 如果我要是想在/var/log/messages中过滤…

『 C++ 』红黑树RBTree详解 ( 万字 )

文章目录 &#x1f996; 红黑树概念&#x1f996; 红黑树节点的定义&#x1f996; 红黑树的插入&#x1f996; 数据插入后的调整&#x1f995; 情况一:ucnle存在且为红&#x1f995; 情况二:uncle不存在或uncle存在且为黑&#x1f995; 插入函数代码段(参考)&#x1f995; 旋转…

阿里云服务器4核8G配置最新优惠价格表(2024活动报价)

阿里云服务器4核8g配置云服务器u1价格是955.58元一年&#xff0c;4核8G配置还可以选择ECS计算型c7实例、计算型c8i实例、计算平衡增强型c6e、ECS经济型e实例、AMD计算型c8a等机型等ECS实例规格&#xff0c;规格不同性能不同&#xff0c;价格也不同&#xff0c;阿里云服务器网al…

Smart Tomcat

Smart Tomcat插件可以让idea图形化界面让代码部署到tomcat上达成一键打包部署的过程 下面是idea安装使用Smart Tomcat的过程 我们直接在plugins(插件)里搜索Tomcat 然后下载第一个 然后点击Apply(应用) 在一个项目中 第一次使用时要进行配置Smart Tomcat Name 可以不配置…

npm超详细安装(包括配置环境变量)!!!npm安装教程(node.js安装教程)

安装node.js:(建议选择相对低一点的版本&#xff0c;相对稳定)​下载完成直接点击next即可(安装过程中会直接添加path的系统变量&#xff0c;变量值是自己的安装路径&#xff0c;可自行选择&#xff0c;比如&#xff1a;D:\software\)​安装完成:winR打开电脑控制台&#xff0c…

【每周AI简讯】GPT-5将有指数级提升,GPT Store正式上线

AI7 - Chat中文版最强人工智能 OpenAI的CEO奥特曼表示GPT-5将有指数级提升 GPT奥特曼参加Y-Combinator W24启动会上表示&#xff0c;我们已经非常接近AGI。GPT-5将具有更好的推理能力、更高的准确性和视频支持。 GPT Store正式上线 OpenAI正式推出GPT store&#xff0c;目前…

20240117-【UNITY 学习】增加墙跑功能和跳墙功能

替换脚本PlayerCam_01.cs using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening;public class PlayerCam_02 : MonoBehaviour {// 视觉灵敏度参数public float sensX 400;public float sensY 400;// 视角垂直旋转角度限制publ…

平衡操控应用场景探讨及RTSP技术实现

平衡操控应用背景 平行操控场景&#xff0c;通过超低延时视频通信技术与实时信令技术结合&#xff0c;使得操作者可以实时的驾驶/操作远端的无人车或机械设备。 相比传统近距离的遥控&#xff0c;平行操控的传输网构建在互联网之上&#xff0c;突破了传统距离限制&#xff0c…

防火墙如何处理nat(私网用户访问Internet场景)

目录 私网用户访问Internet场景源NAT的两种转换方式NAT No-PAT NAPT配置思路规划 NAPT配置命令配置接口IP地址并将接口加入相应安全区域配置安全策略配置NAT地址池配置源NAT策略配置缺省路由配置黑洞路由 私网用户访问Internet场景 多个用户共享少量公网地址访问Internet的时候…

go语言(三)----函数

1、函数单变量返回 package mainimport "fmt"func fool(a string,b int) int {fmt.Println("a ",a)fmt.Println("b ",b)c : 100return c}func main() {c : fool("abc",555)fmt.Println("c ",c)}2、函数多变量返回 pack…