百子作业 —— 中国邮递员问题

题目

严老师和宋老板去勘测武威市区的道路网,每一条路都需要勘测,且需要两人合作.武威市区可以近似地看成六横六纵组成的道路网,自西向东依次为学府路、民勤路、西关路、中关路、富民路、滨河路;自北向南依次为雷海路、宣武路、祁连大道、商业街、南关路、古浪街,任意两个相邻的路口之间的间距均可以认为是500米。
初始时,严老师和宋老板在民勤路与商业街相交的十字路口,最终仍然需要回到这个位置,则他俩至少需要走多少千米?并设计一条路线。

解析

题目对应的图。
在这里插入图片描述
本题是找欧拉回路。路径可以重复走,节点可以重复访问。
由于本题的权是相同的,都是 500 m 500m 500m,因此本题节点虽然多,但是难度降低很多。

求解过程

统计图中点度数

v 11 v_{11} v11 的度数为 2 2 2
v 12 v_{12} v12 的度数为 3 3 3
v 13 v_{13} v13 的度数为 3 3 3
v 14 v_{14} v14 的度数为 3 3 3
v 15 v_{15} v15 的度数为 3 3 3
v 16 v_{16} v16 的度数为 2 2 2
v 21 v_{21} v21 的度数为 3 3 3
v 22 v_{22} v22 的度数为 4 4 4
v 23 v_{23} v23 的度数为 4 4 4
v 24 v_{24} v24 的度数为 4 4 4
v 25 v_{25} v25 的度数为 4 4 4
v 26 v_{26} v26 的度数为 3 3 3
v 31 v_{31} v31 的度数为 3 3 3
v 32 v_{32} v32 的度数为 4 4 4
v 33 v_{33} v33 的度数为 4 4 4
v 34 v_{34} v34 的度数为 4 4 4
v 35 v_{35} v35 的度数为 4 4 4
v 36 v_{36} v36 的度数为 3 3 3
v 41 v_{41} v41 的度数为 3 3 3
v 42 v_{42} v42 的度数为 4 4 4
v 43 v_{43} v43 的度数为 4 4 4
v 44 v_{44} v44 的度数为 4 4 4
v 45 v_{45} v45 的度数为 4 4 4
v 46 v_{46} v46 的度数为 3 3 3
v 51 v_{51} v51 的度数为 3 3 3
v 52 v_{52} v52 的度数为 4 4 4
v 53 v_{53} v53 的度数为 4 4 4
v 54 v_{54} v54 的度数为 4 4 4
v 55 v_{55} v55 的度数为 4 4 4
v 56 v_{56} v56 的度数为 3 3 3
v 61 v_{61} v61 的度数为 2 2 2
v 62 v_{62} v62 的度数为 3 3 3
v 63 v_{63} v63 的度数为 3 3 3
v 64 v_{64} v64 的度数为 3 3 3
v 65 v_{65} v65 的度数为 3 3 3
v 66 v_{66} v66 的度数为 2 2 2

配对

图中,奇点有: v 12 , v 13 , v 14 , v 15 , v 21 , v 26 , v 31 , v 36 , v 41 , v 46 , v 51 , v 56 , v 62 , v 63 , v 64 , v 65 v_{12},v_{13},v_{14},v_{15},v_{21},v_{26},v_{31},\\v_{36},v_{41},v_{46},v_{51},v_{56},v_{62},v_{63},v_{64},v_{65} v12,v13,v14,v15,v21,v26,v31,v36,v41,v46,v51,v56,v62,v63,v64,v65,合计 16 16 16 个。
把他们配对,枚举所有配对,找到代价最小的配对。
由于本题的权值相同,因此,最小配对为 ( v 12 , v 13 ) , ( v 14 , v 15 ) ( v 21 , v 31 ) , ( v 26 , v 36 ) , ( v 41 , v 51 ) , ( v 46 , v 56 ) , ( v 62 , v 63 ) , ( v 64 , v 65 ) (v_{12},v_{13}),(v_{14},v_{15})(v_{21},v_{31}),(v_{26},v_{36}),\\(v_{41},v_{51}),(v_{46},v_{56}),(v_{62},v_{63}),(v_{64},v_{65}) (v12,v13),(v14,v15)(v21,v31),(v26,v36),(v41,v51),(v46,v56),(v62,v63),(v64,v65)

添加重边,去掉奇点

如下图所示,红色为添加的边。
在这里插入图片描述
这样,新图中没有奇点,是一个欧拉图。
注意,将原来图中节点编号按照顺序进行修改,主要是为了计算机编程方便。

答案

最短路径

最短距离 ( 60 + 8 ) ∗ 500 = 34 , 000 m (60+8)*500=34,000m (60+8)500=34,000m,其中 60 60 60 为原有路径, 8 8 8 为构造欧拉图增加的路径。

方案

10 → 4 → 3 → 2 → 1 → 7 → 8 → 2 → 3 → 9 → 8 → 14 → 13 → 7 → 13 → 19 → 20 → 14 → 15 → 9 → 10 → 11 → 5 → 4 → 5 → 6 → 12 → 11 → 17 → 16 → 15 → 21 → 20 → 26 → 25 → 19 → 25 → 31 → 32 → 26 → 27 → 21 → 22 → 23 → 17 → 18 → 12 → 18 → 24 → 23 → 29 → 28 → 27 → 33 → 32 → 33 → 34 → 35 → 29 → 30 → 24 → 30 → 36 → 35 → 34 → 28 → 22 → 16 → 10 10\to 4\to 3\to 2\to 1\to 7\to 8\to 2\to 3\to 9\to 8\to 14\to\\ 13\to 7\to 13\to 19\to 20\to 14\to 15\to 9\to 10\to 11\to 5\to\\ 4\to 5\to 6\to 12\to 11\to 17\to 16\to 15\to 21\to 20\to 26\to\\ 25\to 19\to 25\to 31\to 32\to 26\to 27\to 21\to 22\to 23\to\\ 17\to 18\to 12\to 18\to 24\to 23\to 29\to 28\to 27\to 33\to 32\to\\ 33\to 34\to 35\to 29\to 30\to 24\to 30\to 36\to 35\to 34\to\\ 28\to 22\to 16\to 10 10432178239814137131920141591011545612111716152120262519253132262721222317181218242329282733323334352930243036353428221610
注意:答案不唯一。

C++代码

#include<bits/stdc++.h>
using namespace std;

const int N=1e3+10;
int edge[N][N];
//为了方便优先访问编号小的节点,这里使用邻接矩阵来存边
//如果使用vector来存图,那还需要对每个节点连接的边进行排序
int ans[N*N];
int p=0;//ans指针 
int degree[N];//用于储存每个点的度,以求起点
int n;//节点数量 

void dfs(int now) {
    for (int i=1;i<=n;i++){//顺序寻找可访问的边,优先找编号小的节点
        if (edge[now][i]){//若这条边尚未访问过
            edge[now][i]--;//已访问过的边要删去,防止重复访问
            edge[i][now]--;//有向图的话请删去这一行
            dfs(i);
        }
    }
    ans[++p]=now;//将访问的节点储存进答案数组
    //由于递归的特性,这里储存的是逆序过程
}

int main() {
    ios::sync_with_stdio(false);
    int m;//边的个数
    cin>>n>>m;
    for(int i=1;i<=m;i++) {
        int a,b;
        cin>>a>>b>>c;
        edge[a][b]++;
        edge[b][a]++;//有向图的话删去这行
        degree[a]++;
		degree[b]++;//两个点的度都+1
    }
    int start;//起点 
    cin>>start;
    dfs(start);//dfs寻找欧拉路
    cout<<(p-1)*500<<"\n";//计算总代价 
    for(int i=p;i>=1;i--) {
        cout<<ans[i]<<" ";//输出给定的欧拉路
	}
    cout<<"\n";
    return 0; 
}

对应的测试数据如下。

36 68
1 2 500
2 3 500
2 3 500
3 4 500
4 5 500
4 5 500
5 6 500
1 7 500
2 8 500
3 9 500
4 10 500
5 11 500
6 12 500
7 8 500
8 9 500
9 10 500
10 11 500
11 12 500
7 13 500
7 13 500
8 14 500
9 15 500
10 16 500
11 17 500
12 18 500
12 18 500
13 14 500
14 15 500
15 16 500
16 17 500
17 18 500
13 19 500
14 20 500
15 21 500
16 22 500
17 23 500
18 24 500
19 20 500
20 21 500
21 22 500
22 23 500
23 24 500
19 25 500
19 25 500
20 26 500
21 27 500
22 28 500
23 29 500
24 30 500
24 30 500
25 26 500
26 27 500
27 28 500
28 29 500
29 30 500
25 31 500
26 32 500
27 33 500
28 34 500
29 35 500
30 36 500
31 32 500
32 33 500
32 33 500
33 34 500
34 35 500
34 35 500
35 36 500
1
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值