使用DFS求任意两点间所有路径

算法具体原理就不讲了,无非是当要返回到前一个结点时将该结点重新设置为未访问。

void DFS(int start, int end)
{
	if (start == end) {//找到终点
		path.push_back(start);//将终点加入path
		for (int i = 0; i < path.size(); i++) //输出路径
		{
			if (i != path.size() - 1)
				cout << inverse_maping[path[i]] << "->";
			else
				cout << inverse_maping[path[i]] << "\n";
		}
		path.pop_back();//删除最后一个节点
		vis[start] = false;//终点重新设置为未访问
		return;
	}
    vis[start] =true;   //将当前结点设置为已访问 
	path.push_back(start);//加入路径
	for (int j =0; j < Adj[start].size(); j++) {//遍历所有子结点
		int v = Adj[start][j];//在邻接表中查找子结点v的结点号
		if (!vis[v] && path.size()<4) {//检查该节点是否被访问, 
		                           //path.size()<4可以限制输出的最大的路径长度
			DFS(v, end);          //当前是仅输出起点到终点间的结点数目<=2的路径
		}
		if (j == Adj[start].size() - 1 ) {//子结点全部遍历完成
			path.pop_back();//删除路径中最后一个节点
			vis[start] = false;//设置为未访问
			return;
		}
	}
}

这里给出一个之前实习的问题:
这次疫情湖北受灾严重,那么为什么湖北这么重要,试证明湖北到全国其他省(不包括两个宝岛)中间都不超过2个省。给定图邻接关系city
用DFS求解湖北到其他所有省份的中间不超过2个省的路径并全部输出(例如:湖北-江西-浙江;湖北-陕西-内蒙古-黑龙江)

#include <string>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>

using namespace std;
const int MAXV = 34;//最大结点数
int n;//结点数
bool vis[MAXV] = { false }; //DFS中判断结点是否被访问
vector<int> Adj[MAXV]; //DFS的邻接表
vector<int> path;//DFS的路径
map<string,int>mapping; //完成城市名与结点编号的映射
map<int, string>inverse_maping;//完成结点编号与城市名的映射
string city[MAXV][10] = {	//城市间的邻接关系
	{ "内蒙古", "黑龙江", "吉林", "辽宁", "河北", "山西", "陕西", "宁夏", "甘肃" },
	{ "黑龙江", "内蒙古", "吉林" },
	{"吉林", "黑龙江", "内蒙古", "辽宁" },
	{"辽宁", "吉林", "内蒙古", "河北"},
	{"河北", "辽宁", "内蒙古", "山西", "北京", "天津", "山东", "河南"},
	{"河南", "河北", "湖北", "陕西", "山西", "安徽", "山东"},
	{"山东", "河北", "河南", "安徽", "江苏"},
	{"北京", "河北", "天津"},
	{"天津", "河北", "北京"},
	{"山西", "河北", "内蒙古", "陕西", "河南"},
	{"陕西", "宁夏", "内蒙古", "甘肃", "河南", "山西", "四川", "重庆", "湖北"},
	{"宁夏", "陕西", "内蒙古", "甘肃"},
	{"甘肃", "宁夏", "内蒙古", "陕西", "青海", "新疆", "四川"},
	{"青海", "甘肃", "西藏", "新疆", "四川"},
	{"新疆", "西藏", "甘肃", "青海"},
	{"西藏", "新疆", "青海", "四川", "云南"},
	{"四川", "青海", "西藏", "甘肃", "陕西", "云南", "贵州", "重庆"},
	{"云南", "西藏", "四川", "贵州", "广西"},
	{"重庆", "陕西", "四川", "贵州", "湖南", "湖北"},
	{"贵州", "重庆", "四川", "云南", "广西", "湖南"},
	{"广西", "云南", "贵州", "湖南", "广东"},
	{"广东", "福建", "江西", "湖南", "广西", "香港", "澳门"},
	{"湖南", "湖北", "重庆", "贵州", "广西", "广东", "江西"},
	{"江西", "安徽", "湖北", "湖南", "广东", "福建", "浙江"},
	{"福建", "浙江", "江西", "广东"},
	{"湖北", "河南", "陕西", "重庆", "湖南", "江西", "安徽"},
	{"河南", "河北", "山西", "陕西", "湖北", "安徽", "江苏", "山东"},
	{"安徽", "河南", "湖北", "江西", "浙江", "江苏", "山东"},
	{"浙江", "上海", "江苏", "安徽", "江西", "福建"},
	{"上海", "江苏", "浙江"},
	{"江苏", "山东", "安徽", "浙江", "上海"},
	{"山东", "河北", "河南", "江苏"},
	{"香港", "广东"},
	{"澳门", "广东"}};


void creat_graph()//将中文关系转换为整型邻接表,并完成城市名与结点编号的映射;
{
	for (int i = 0; i < MAXV; i++)//开始映射
	{
		mapping[city[i][0]] = i;
		inverse_maping[i] =city[i][0];
	}
	//for (map<string, int>::iterator it = mapping.begin(); it != mapping.end(); it++)
	//printf("%s %d\n", it->first.c_str(), it->second);
	for (int i = 0; i < 34; i++)
	for (int j = 1; j < sizeof(city[i]); j++)
	{
		if (city[i][j] == "")
			break;
		Adj[i].push_back(mapping[city[i][j]]);//建立int型邻接表
	}
}

void DFS(int start, int end)
{
	if (start == end) {//找到终点
		path.push_back(start);
		for (int i = 0; i < path.size(); i++) 
		{
			if (i != path.size() - 1)
				cout << inverse_maping[path[i]] << "->";//输出从栈底到栈顶的元素,即为一条路径
			else
				cout << inverse_maping[path[i]] << "\n";
		}
		path.pop_back();
		vis[start] = false;
		return;
	}
    vis[start] =true;    
	path.push_back(start);
	for (int j =0; j < Adj[start].size(); j++) {

		int v = Adj[start][j];
		if (!vis[v] && path.size()<4) {
			DFS(v, end);
		}
		if (j == Adj[start].size() - 1 ) {
			path.pop_back();
			vis[start] = false;
			return;
		}
	}
}
int main()
{
	creat_graph();
	
	for (map<string, int>::iterator it = mapping.begin(); it != mapping.end();it++)
		if (it->first!="湖北")
		DFS(mapping["湖北"],mapping[it->first]);//查找湖北到其它所有城市路径总长度不
		                                       //超过4的路径
	return 0;
}

部分结果:
湖北->河南->安徽
湖北->河南->江苏->安徽
湖北->陕西->河南->安徽
湖北->湖南->江西->安徽



湖北->湖南->贵州->重庆
湖北->江西->湖南->重庆

  • 15
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值