[C++]有向图的简单路径

一、题目描述

(1).求出有向图中从起点到终点的所有简单路径。其中起点和终点可以由用户自行设定。
(2).求出有向图中从起点到终点的指定长度(如K)的所有简单路径。其中起点和终点可以由用户自行设定。

二、解决方案

1.任务定义和问题分析

  • 首先建立图的邻接矩阵来表示图,0表示无边,非0的n代表边的权值(边的长度);
  • 用vector < int > path储存路径(path记录图的点来表示路径);
  • 采用BFS(深度遍历)的方法来遍历所有的路径,符合的路径则进path并输出;

2.详细设计

a.建一个图的类,类里包含邻接矩阵的建立以及BFS算法的实现

#include<iostream>
#include<vector>
using namespace std;

class figure
{
private:
	vector<int> path;//储存路径
	int count;//图中点的个数
	int** sz;//动态二维邻接矩阵数组的创立
	int start;//起点
	int end;//终点
	int goal;//指定的路径长度
	int temp;//path里的路径长度
public:
	figure(int n, int start, int end, int k);//为邻接矩阵二维数组开空间,起点、终点、路径长度的确立
	~figure();
	void creat();//建立邻接矩阵
	void dfs_findall(int v);//查找从起点到终点的所有路径(BFS遍历)
	void dfs_findspecial(int v);//查找从起点到终点路径长度为goal的所有路径(BFS遍历)
	void cout_path();//输出路径
	int firstadj(int v, int cou);//查找下一个临接点
	bool judge_circle(int &v, int &next);//判断此时的路径是简单路径(路径是否有环)
};

b.图的构造和析构函数:邻接矩阵二维数组开空间,起点、终点、路径长度的确立

figure::figure(int n, int sta, int en, int k)
{
	start = sta;
	end = en;
	goal = k;
	temp = 0;//现在路径的长度为0;
	path.push_back(start);//现将起点放到路径里
	count = n;
	sz = new int* [n];
	for (int i = 0; i < n; i++)
	{
		sz[i] = new int[n];
	}
}
figure::~figure()
{
	delete[]sz;
}

c.建立邻接矩阵:

void figure::creat()
{
	int i, j, a;
	for (i = 0; i < count; i++)
	{
		for (j = 0; j < count; j++)
		{
			cin >> a;
			sz[i][j] = a;
		}
	}
}

d.查找从起点到终点的所有路径(BFS遍历)

void figure::dfs_findall(int v)//v代表现在遍历的点
{
	if (v == end)//如果现在的点==终点输出路径并返回上一级
	{
		cout_path();
		return;
	}
	int cou = 0;//v可能与多个点连接,cou表示:v相邻的第cou+1个点,此时cou=0表示与cou相邻的第1个点,
	int next = firstadj(v, cou);//取得v相邻的第cou+1个点,
	while (next != -1)//因为邻接矩阵的点为0,1,2,3,4......n没有负数的点,当点数为-1时代表v没有相邻的点了
	{
		while (judge_circle(v, next))//判断是否为简单路径,如果不是,再寻找下一个不和当前路径有环的相邻点
		{
			cou++;
			next = firstadj(v, cou);
		}
		path.push_back(next);
		dfs_findall(next);//开始BFS
		path.pop_back();//回溯所做的工作,将path回溯到之前的状态
		v = path.back();
		cou++;//取v的下一个邻接点
		next = firstadj(v, cou);
	}
}

e.查找从起点到终点路径长度为goal的所有路径(BFS遍历),其思路与d.查找从起点到终点的所有路径(BFS遍历)类似,只是输出条件变了,多用了记录路径长度的temp,当现在的点v终点&&temp指定路径长度时,输出路径;

void figure::dfs_findspecial(int v)
{
	if (v == end && temp == goal)//当现在的点v==终点&&temp==指定路径长度时,输出路径;
	{
		cout_path();
		return;
	}
	if (v == end)//如果v==终点,但不是指定路径也返回
		return;
	int cou = 0;//v可能与多个点连接,cou表示:v相邻的第cou+1个点,此时cou=0表示与cou相邻的第1个点,
	int next = firstadj(v, cou);//取得v相邻的第cou+1个点,
	while (next != -1)//判断是否为简单路径,如果不是,再寻找下一个不和当前路径有环的相邻点
	{
		while(judge_circle(v, next))
		{
			cou++;
			next = firstadj(v, cou);
		}
		vector<int>::iterator it = path.end()-1;
		path.push_back(next);
		temp += sz[*it][path.back()];//邻接矩阵数组的数据代表边的长度
		dfs_findspecial(next);//开始BFS
		temp -= sz[*it][path.back()];//回溯所做的工作,将path回溯到之前的状态
		path.pop_back();
		v = path.back();
		cou++;
		next = firstadj(v, cou);//取v的下一个邻接点
	}
}

f.输出路径的函数

void figure::cout_path()
{
	vector<int>::iterator it = path.begin();
	for (; it < path.end() - 1; it++)
		cout << *it << "->";
	cout << *it << endl;
}

g.得到下一个邻接点的函数

int figure::firstadj(int v, int cou)
{
	int i, a = -1, k = 0;//k是记录现在v的第k+1个点;
	for (i = 0; i < count; i++)
	{
		if (sz[v][i] != 0)//如果此点存在
		{
			if (k == cou)//判断是否是要取v的第cou+1的点,如果是就返回
			{
				a = i;
				break;
			}
			k++;
			if (k > cou)
				break;
		}
	}
	return a;
}

h.判断v的邻接点如果进入路径是否仍然还是简单路径,将路径的所有点与邻接点比较,如果有重合的点(除了起点与终点)就不是简单路径

bool figure::judge_circle(int &v, int &next)
{
	//将路径的所有点与邻接点比较,如果有重合的点(除了起点与终点)就不是简单路径
	for (vector<int>::iterator it = path.begin()+1; it < path.end()-1; it++)
		if (*it == next)
			return true;
	return false;
}

i.路径输出函数

void figure::cout_path()
{
	vector<int>::iterator it = path.begin();
	for (; it < path.end() - 1; it++)
		cout << *it << "->";
	cout << *it << endl;
}

三、输出样例

样例一:

在这里插入图片描述
在这里插入图片描述

样例二:

在这里插入图片描述
在这里插入图片描述

四、源码地址

源码地址

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值