求解无向图的最小哈密尔顿回路

目录

1.题目

2.前置知识: 多叉树的遍历

​编辑

3.代码

算法分析

3.运行结果


1.题目

来自离散数学的一道作业题,本文将解第(3)问

2.前置知识: 多叉树的遍历

和这道题L56.【LeetCode题解】 电话号码的字母组合非常像,强烈建议各位读者去看看 ;-)

3.代码

算法分析

对a~e进行有序排列组合,根据排列组合公式,显然一共A_5^5种情况,枚举方法:使用多叉树

如果a是回路的起点,那么有以下多叉树图:

可以发现:

1.递归层数为5

2.回路的节点只有首和尾是重复的,其余节点不能重复,要想在递归过程避开重复节点,需要记忆化处理,即使用一个set存储路径上遍历过的节点,这里和电话号码的字母组合那题不一样

3.将找出的所有回路存储到multimap <int, string> mp中,因为回路长度相同的结果有多个,例如:

a->b->c->d->e->a和a->c->d->b->e->a长度都是20

4.两节点之间的长度使用二维数组存储

5.人工手动一一列举太麻烦,直接DFS遍历多叉树所有情况即可

#include <iostream>
#include <string>
#include <set>
#include <map>
using namespace std;
void dfs(char node, size_t len, size_t arr[123][123], size_t level, string path, set<char>& status, size_t& num, multimap <int, string>& mp)
{
	if (level == 5)
	{
		path += path[0];
		len += arr[path[path.size() - 2]][path[0]];
		cout << path << ":" << len << endl;
		mp.insert(pair<size_t, string>(len, path));
		num++;
		return;
	}
	for (char i = 'a'; i <= 'e'; i++)
	{
		if (status.count(i) == 0)
		{
			path += i;
			status.insert(i);
			dfs(i, len + arr[node][i], arr, level + 1, path, status, num, mp);
			status.erase(i);//回归后必须删除后才能正确参与下次递归!
			path.pop_back();//同时删除路径上的节点
		}

	}
	return;
}

int main()
{
	//存储长度信息
	static size_t arr['z' + 1]['z' + 1];
	arr['a']['b'] = 5;
	arr['a']['c'] = 4;
	arr['a']['d'] = 5;
	arr['a']['e'] = 8;

	arr['b']['a'] = 5; 
	arr['b']['c'] = 2;
	arr['b']['d'] = 2;
	arr['b']['e'] = 3;

	arr['c']['a'] = 4;
	arr['c']['b'] = 2;
	arr['c']['d'] = 3;
	arr['c']['e'] = 5;

	arr['d']['a'] = 5;
	arr['d']['b'] = 2;
	arr['d']['c'] = 3;
	arr['d']['e'] = 2;

	arr['e']['a'] = 8;
	arr['e']['b'] = 3;
	arr['e']['c'] = 5;
	arr['e']['d'] = 2;

	//递归枚举所有情况
	size_t num = 0;
	multimap <int, string> mp;
	cout << "所有的哈密尔顿回路:" << endl;
	for (char c = 'a'; c <= 'e'; c++)
	{
		string path;
		set<char> status;
		status.insert(c);
		path += c;
		dfs(c, 0, arr, 1, path, status, num, mp);
	}
	cout << "无向完全图的所有哈密尔顿回路一共" << num << "种可能";
	size_t min_len = (*mp.begin()).first;
	cout << "其中路径的最短长度为" << min_len << ",有以下几种方案:" << endl;
	for (auto i = mp.begin(); i != mp.end(); i++)
		if (i->first == min_len)
			cout << i->second << endl;
		else
			break;
}

3.运行结果

所有的哈密尔顿回路:

 最短路径的方案:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zhangcoder

赠人玫瑰手有余香,感谢支持~

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

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

打赏作者

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

抵扣说明:

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

余额充值