news 2026/3/11 3:14:37

骑马修栅栏(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/3/2 2:42:01

DLSS-Enabler终极指南:免费解锁非NVIDIA显卡的DLSS魔法

DLSS-Enabler终极指南&#xff1a;免费解锁非NVIDIA显卡的DLSS魔法 【免费下载链接】DLSS-Enabler Simulate DLSS Upscaler and DLSS-G Frame Generation features on any DirectX 12 compatible GPU in any DirectX 12 game that supports DLSS2 and DLSS3 natively. 项目地…

作者头像 李华
网站建设 2026/3/10 13:33:28

FastGPT AI知识库:零基础搭建智能电商客服的完整指南

FastGPT AI知识库&#xff1a;零基础搭建智能电商客服的完整指南 【免费下载链接】FastGPT labring/FastGPT: FastGPT 是一个基于PyTorch实现的快速版GPT&#xff08;Generative Pretrained Transformer&#xff09;模型&#xff0c;可能是为了优化训练速度或资源占用而设计的一…

作者头像 李华
网站建设 2026/3/7 19:16:01

SGMICRO圣邦微 SGM2203-2.5YN3LG/TR SOT-23 线性稳压器(LDO)

特性高输入电压&#xff1a;最高36V固定输出电压&#xff1a;2.5V、2.8V、3.0V、3.3V、3.5V、3.6V、4.0V、4.2V、5.0V、5.75V、8.0V、9.0V和12V150mA输出电流输出电压精度&#xff1a;25C时为3%低压差电压低功耗&#xff1a;4.2μA&#xff08;典型值&#xff09;低温漂系数限流…

作者头像 李华
网站建设 2026/3/6 5:38:23

SGMICRO圣邦微 SGM2202-2.8YN5G/TR SOT23-5 线性稳压器(LDO)

特性 高输入电压:最高可达36伏 固定输出电压:2.5V、2.8V、3.0V、3.3V、5.0V 可调输出电压:0.8V至13.2V 150毫安保证输出电流 输出电压精度:25C时士2.5% 高PSRR:在1kHz时为40dB(典型值) 低压差电压 低功耗:4.2uA(典型值) 关断供电电流:1.5uA(典型值) 低温系数 热关断保护 输出电…

作者头像 李华
网站建设 2026/3/10 20:19:03

springboot房产租赁管理系统设计实现

背景分析房产租赁管理系统在数字化时代的需求日益增长。传统租赁管理依赖纸质合同和人工记录&#xff0c;存在效率低、易出错、信息不透明等问题。随着城市化进程加速和流动人口增多&#xff0c;租赁市场的规范化、透明化需求迫切。SpringBoot作为轻量级Java框架&#xff0c;能…

作者头像 李华