DS图—图的最短路径(无框架)

题目描述

给出一个图的邻接矩阵,输入顶点v,用迪杰斯特拉算法求顶点v到其它顶点的最短路径。

输入

第一行输入t,表示有t个测试实例

第二行输入顶点数n和n个顶点信息

第三行起,每行输入邻接矩阵的一行,以此类推输入n行

第i个结点与其它结点如果相连则为距离,无连接则为0,数据之间用空格

隔开。第四行输入v0,表示求v0到其他顶点的最短路径距离

以此类推输入下一个示例

输出

对每组测试数据,输出:

每行输出v0到某个顶点的最短距离和最短路径

每行格式:v0编号-其他顶点编号-最短路径值----[最短路径]。没有路径输出:v0编号-其他顶点编号--1。具体请参考示范数据

输入样例1

2
5 0 1 2 3 4
0 5 0 7 15
0 0 5 0 0
0 0 0 0 1
0 0 2 0 0
0 0 0 0 0
0
6 V0 V1 V2 V3 V4 V5
0 0 10 0 30 100
0 0 5 0 0 0
0 0 0 50 0 0
0 0 0 0 0 10
0 0 0 20 0 60
0 0 0 0 0 0
V0

输出样例1

0-1-5----[0 1 ]
0-2-9----[0 3 2 ]
0-3-7----[0 3 ]
0-4-10----[0 3 2 4 ]
V0-V1--1
V0-V2-10----[V0 V2 ]
V0-V3-50----[V0 V4 V3 ]
V0-V4-30----[V0 V4 ]
V0-V5-60----[V0 V4 V3 V5 ]
 

NOTICE:

正题:(1)题目输入时是以0来表示无连接,但在我们的算法中,带权值的邻接矩阵是以无穷来表示,因此在输入时要注意;(2)迪杰斯特拉算法(Dijkstra)中需要的变量有:D数组、final数组、path数组、flag,各个变量的作用在代码中注释;此算法与Prim算法大体上相似,但在很多实现细节上略有区别;(3)初始化时要注意flag为起点下标,起点的final和path做出相应修改,D初始化为起点到各个顶点的权值(区别于Prim是全部初始化为无穷),如果权值不为无穷,则修改相应的path,final除起点外全为0;初始化工作有点复杂感觉,很容易搞错,比如这里先把所有的final改为0后再单独把起点的final改为1;(4)循环主要分两个工作,一个是找flag,一个是更新D值;flag是D中最小且final为0的顶点的下标,找到后记得改final为1;更新D的条件要注意,是相加后小于,更新后记得修改path;(5)输出部分根据题目要求来即可,注意怎么判断一个顶点无最短路径:其D值为无穷

错误思路:一开始真的觉得这个算法跟Prim太像了,所以一开始初始化时跟Prim的做法一样,后来发现这样的话更新D时会出错,做法不可取,还是得根据ppt上例子的表格来推进这个算法

#include <iostream>
#include <stack>
using namespace std;
#define MAX 65535

class Graph
{
private:
	string* data;
	int** Matrix;
	int vertexnum;
	string v;//最短路径的起点
	int find(string s)
	{
		for (int i = 0; i < vertexnum; i++)
			if (s == data[i])
				return i;
	}
public:
	Graph()
	{
		cin >> vertexnum;
		data = new string[vertexnum];
		for (int i = 0; i < vertexnum; i++)
			cin >> data[i];
		Matrix = new int* [vertexnum];
		for (int i = 0; i < vertexnum; i++)
			Matrix[i] = new int[vertexnum];
		for (int i = 0; i < vertexnum; i++)
			for (int j = 0; j < vertexnum; j++)
			{
				cin >> Matrix[i][j];
				if (Matrix[i][j] == 0)//输入为0,表示两点之间无连接,修改为无穷
					Matrix[i][j] = MAX;
			}
				
		cin >> v;
	}
	~Graph()
	{
		delete[]data;
		for (int i = 0; i < vertexnum; i++)
			delete[]Matrix[i];
		delete[]Matrix;
	}
	void Dijkstra()
	{
		int* D = new int[vertexnum];//从顶点出发到某个顶点的当前最短路径长度(更新)
		int* final = new int[vertexnum];//某个顶点是否已经加入到U集合中
		int* path = new int[vertexnum];//每个顶点的最短路径上,到达该顶点的上一个顶点的下标
		int flag;//D值最小且final为0的顶点的下标


		//初始化
		flag = find(v);
		path[flag] = -1;
		for (int i = 0; i < vertexnum; i++)
		{
			D[i] = Matrix[flag][i];

			if (D[i] != MAX)
				path[i] = flag;

			final[i] = 0;
		}
		final[flag] = 1;
			
		//循环
		for (int i = 0; i < vertexnum - 1; i++)
		{
			//找flag
			int tmp = MAX;
			for (int j = 0; j < vertexnum; j++)
				if (final[j] == 0 && D[j] < tmp)
				{
					tmp = D[j];
					flag = j;
				}
			final[flag] = 1;


			//更新D
			for (int j = 0; j < vertexnum; j++)
				if (D[flag] + Matrix[flag][j] < D[j])
				{
					D[j] = D[flag] + Matrix[flag][j];
					path[j] = flag;
				}
		}

		//输出
		for (int i = 0; i < vertexnum; i++)
		{
			//特殊情况,无最短路径
			if (i != find(v) && D[i] == MAX)
			{
				cout << data[find(v)] << "-" << data[i] << "--1" << endl;
				continue;
			}
			if (i != find(v))
			{
				cout << data[find(v)] << "-" << data[i] << "-" << D[i] << "----[";
				//输出路径
				int k = i;
				stack<int> s;
				while (k != -1)
				{
					s.push(k);
					k = path[k];
				}
				while (!s.empty())
				{
					cout << data[s.top()] << " ";
					s.pop();
				}
				cout << "]" << endl;
			}
		}
	}
};

int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		Graph g;
		g.Dijkstra();
	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值