news 2026/5/1 8:45:40

骑马修栅栏(fence)(信息学奥赛一本通- P1375)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
骑马修栅栏(fence)(信息学奥赛一本通- P1375)

【题目描述】

农民John每年有很多栅栏要修理。他总是骑着马穿过每一个栅栏并修复它破损的地方。

John是一个与其他农民一样懒的人。他讨厌骑马,因此从来不两次经过一个一个栅栏。你必须编一个程序,读入栅栏网络的描述,并计算出一条修栅栏的路径,使每个栅栏都恰好被经过一次。John能从任何一个顶点(即两个栅栏的交点)开始骑马,在任意一个顶点结束。

每一个栅栏连接两个顶点,顶点用1到500标号(虽然有的农场并没有500个顶点)。一个顶点上可连接任意多(≥1)个栅栏。所有栅栏都是连通的(也就是你可以从任意一个栅栏到达另外的所有栅栏)。

你的程序必须输出骑马的路径(用路上依次经过的顶点号码表示)。我们如果把输出的路径看成是一个500进制的数,那么当存在多组解的情况下,输出500进制表示法中最小的一个 (也就是输出第一个数较小的,如果还有多组解,输出第二个数较小的,等等)。 输入数据保证至少有一个解。

【输入】

第1行:一个整数F(1≤F≤1024),表示栅栏的数目;

第2到F+1行:每行两个整数i,j(1≤=i,j≤500)表示这条栅栏连接i与j号顶点。

【输出】

输出应当有F+1行,每行一个整数,依次表示路径经过的顶点号。注意数据可能有多组解,但是只有上面题目要求的那一组解是认为正确的。

【输入样例】

9 1 2 2 3 3 4 4 2 4 5 2 5 5 6 5 7 4 6

【输出样例】

1 2 3 4 2 5 4 6 5 7
1. 什么是欧拉路(一笔画)?

简单来说,就是“走完所有的边,且每条边只走一次”。

  • 如果能回到起点,叫欧拉回路

  • 如果回不到起点,叫欧拉通路

做这种题,别去脑补怎么画,直接套用Hierholzer 算法(DFS + 栈)

2. 踩坑提醒:这两个地方最容易wa

刚才做题时,我有两个地方写错了,调了半天才发现。这两个坑非常典型,同学们一定要注意:

易错点一:邻接矩阵要存“数量”而不是“状态”

  • 错误写法g[u][v] = 1;

  • 原因:题目中两个点之间可能有多条边(比如 1 和 2 之间有两道栅栏)。如果只存 1,就会覆盖掉之前的边,导致少走一条路。

  • 正确写法:用g[u][v]++累加边的数量,删边时用g[u][v]--

易错点二:起点的选择逻辑

  • 错误写法:只找奇点(度数为奇数的点)出发,找不到就直接结束。

  • 原因:如果是一张欧拉回路图(所有点度数都是偶数),循环里根本找不到奇点,程序会没有任何输出。

  • 正确写法

    1. 优先找奇点(如果有,一定是 2 个,选编号小的那个)。

    2. 如果没找到奇点,说明是回路,默认从编号最小的有边节点(通常是 1)出发。

3. 核心算法逻辑

不要在“进递归”的时候输出,要在“回溯”(路走不通了要退回来)的时候把点记录下来。

因为我们是在“退回来”的时候记录的,所以路径是倒序的。

解决办法:用一个 栈把点存进去,最后弹出来就是正序路径。

4.完整代码
#include <iostream> #include <stack> //因为是倒着回溯输出的,所以输出与路线刚好相反,就存进栈 using namespace std; int g[510][510]; int d[510];//记录每个节点连接的边数 int ma=1;//记录有多少个点 stack<int> s; void dfs(int x){ for(int i=1;i<=ma;i++){ if(g[x][i]>0){//如果有栅栏就必须走 g[x][i]--;//然后把栅栏标记为走过 g[i][x]--; dfs(i); } } //路走完了,回溯时进栈 s.push(x); } int main(){ int f; cin>>f; for(int i=1;i<=f;i++){ int u,v; cin>>u>>v;//栅栏是双向的 g[u][v]++;//容易出错的地方 可能不止一个栅栏 g[v][u]++; d[u]++; d[v]++; ma=max(ma,u); ma=max(ma,v); } for(int i=1;i<=ma;i++){ if(d[i]%2==1){//如果是欧拉通路 无向图一笔画要从连接奇数个边的点作为起点 dfs(i); while(!s.empty()){//栈先入后出原则 刚好把倒着存进去的按照正确路线输出 cout<<s.top()<<endl; s.pop(); } return 0; } } //没有找到连接奇数个边的点就是欧拉回路 dfs(1); while(!s.empty()){//栈先入后出原则 刚好把倒着存进去的按照正确路线输出 cout<<s.top()<<endl; s.pop(); } return 0; }
5. 总结

遇到“经过所有边”的题:

  1. 先看度数判断能不能画出来(奇点只能是 0 个或 2 个)。

  2. 用邻接矩阵++存边,防重边。

  3. DFS 回溯入栈,最后倒序输出。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/29 6:24:09

Keil开发环境头文件配置实战案例解析

Keil找不到头文件&#xff1f;一文搞懂头文件路径配置的“坑”与“道”你有没有遇到过这样的场景&#xff1a;刚接手一个别人的Keil工程&#xff0c;打开就满屏红波浪线&#xff1b;或者自己辛辛苦苦写了半天代码&#xff0c;一编译——fatal error: xxx.h: No such file or di…

作者头像 李华
网站建设 2026/5/1 6:08:07

清华源提供API查询最新TensorFlow包信息

清华源 API 查询最新 TensorFlow 包信息&#xff1a;构建高效 AI 开发环境的实用路径 在深度学习项目启动阶段&#xff0c;你是否曾因 pip install tensorflow 卡在 10% 而反复重试&#xff1f;是否在团队协作中遭遇“我的代码在你机器上跑不通”的尴尬&#xff1f;这些看似琐…

作者头像 李华
网站建设 2026/5/1 7:20:01

GCViewer终极指南:5步轻松掌握Java性能优化利器

GCViewer终极指南&#xff1a;5步轻松掌握Java性能优化利器 【免费下载链接】GCViewer Fork of tagtraum industries GCViewer. Tagtraum stopped development in 2008, I aim to improve support for Suns / Oracles java 1.6 garbage collector logs (including G1 collector…

作者头像 李华
网站建设 2026/4/18 4:57:45

springboot个人物品管理系统设计实现

背景分析个人物品管理需求日益增长&#xff0c;传统的手工记录或简单电子表格方式存在效率低、易丢失、检索困难等问题。随着移动互联网和物联网技术普及&#xff0c;用户对高效、可视化的物品管理工具需求显著提升。技术背景Spring Boot作为轻量级Java框架&#xff0c;具备快速…

作者头像 李华
网站建设 2026/5/1 7:23:10

ExoPlayer实战宝典:从入门到精通Android视频播放开发

ExoPlayer实战宝典&#xff1a;从入门到精通Android视频播放开发 【免费下载链接】ExoPlayer An extensible media player for Android 项目地址: https://gitcode.com/gh_mirrors/exop/ExoPlayer 还在为Android视频播放的复杂适配而烦恼吗&#xff1f;是否经常遇到不同…

作者头像 李华
网站建设 2026/5/1 7:23:37

Xenia GPU模拟器终极指南:5步实现Xbox 360游戏完美运行

Xenia GPU模拟器终极指南&#xff1a;5步实现Xbox 360游戏完美运行 【免费下载链接】xenia Xbox 360 Emulator Research Project 项目地址: https://gitcode.com/gh_mirrors/xe/xenia Xenia GPU模拟器是一款专为PC平台设计的开源Xbox 360模拟器&#xff0c;通过先进的图…

作者头像 李华