实现有向图的Dijkstra最短路径算法

实现有向图的Dijkstra最短路径算法,输入起始顶点Vi和终止顶点Vj,输出从Vi到Vj的最短路径及其长度。
在此基础上,借助OpenCV将图及其上从Vi到Vj的最短路径画出来。函数Dijkstra()  ->  源文件Dijkstra.cpp

效果图如下

input.txt内容如下

1 2 10
1 6 8
2 1 10
2 3 12
2 4 15
3 2 12
3 5 6
4 2 15
4 5 7
5 3 6
5 4 7
6 1 8
6 7 5
6 8 20
7 6 5
7 8 14
8 6 20
8 7 14
7 9 5
9 10 9
10 9 9

代码如下:代码段中有详细注释

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <iostream>
#include<math.h>
#include<stdlib.h>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
/*第11次数据结构作业
(1) 实现有向图的Dijkstra最短路径算法,输入起始顶点Vi和终止顶点Vj,输出从Vi到Vj的最短路径及其长度。
在此基础上,借助OpenCV将图及其上从Vi到Vj的最短路径画出来。函数Dijkstra()  ->  源文件Dijkstra.cpp
(2) 实现有向图的拓扑排序和关键路径算。在此基础上,借助OpenCV将图及其关键路径画出来。函数CriticalPath() -> 源文件CriticalPath.cpp*/
Mat P(600, 800, CV_8UC3, Scalar(255, 255, 255));
int a[50], b[50], c[50];//初始化时用的初始点 终点 权值
int distances[15];//初始点到其他各点的距离
int route[10];//每个节点最短路径的前驱
int found[10];//标识该节点是否找到最短路径
#define MAX_DATA 9999
struct datas//点的颜色
{
	int r, g, b;
}color[11];
struct location//点的位置
{
	int x, y;
}local[11];

void startdata()//颜色 坐标初始值
{
	int i;
	for (i = 1; i < 11; i++)
	{
		color[i].r = rand() % 255;
		color[i].b = rand() % 255;
		color[i].g = rand() % 255;
	}
	local[1].x = 400; local[1].y = 50; local[2].x = 280; local[2].y = 100; local[3].x = 170; local[3].y = 200; local[4].x = 330; local[4].y = 200;
	local[5].x = 240; local[5].y = 320; local[6].x = 500; local[6].y = 110; local[7].x = 510; local[7].y = 250; local[8].x = 600; local[8].y = 250;
	local[9].x = 520; local[9].y = 400; local[10].x = 650; local[10].y = 400;
}
int seek()// 寻找当前最小的路径 在未获取最短路径的顶点中,找到离i最近的顶点u
{
	int i, min=MAX_DATA, min_position=-1;
	for (i = 0; i < 10; i++)
	{
		if (distances[i] < min && !found[i])
		{
			min = distances[i];
			min_position = i;
		}
	}
	return min_position;
}
void Dijkstra(int v, int t,int cost[][15], int n)//Dijkstra最短路算法
{
	int i, u, w; 
	int temp[10] = { 0 };
	for (i = 1; i <= n; i++)//初始化
	{
		found[i] = 0;//顶点i的最短路径还未得到
		distances[i] = cost[v][i];// 初始化顶点i的最短路径为顶点v到顶点i的权
		route[i] = 1;//初始化顶点i的前驱顶点为1
	}
	found[v] = 1;//初始点的最短路径已经得到
	distances[v] = 0;//初始点v的最短路径为0
	for (i = 0; i < n-1; i++)
	{
		u = seek(); // 寻找当前最小的路径 在未获取最短路径的顶点中,找到离i最近的顶点u
		found[u] = 1; // 标记顶点u为已经获取到最短路径
		for(w=1;w<=n;w++)// 修正当前最短路径和前驱顶点.即当已经顶点k的最短路径之后,更新未获取最短路径的顶点的最短路径和前驱顶点
		{ 
			if(!found[w]&& distances[u] + cost[u][w] < distances[w])
				{
					route[w] = u;//顶点w的前驱设置为u
					distances[w] = distances[u] + cost[u][w];//更新该顶点的最短路径
				}
		}
	}
	while (t != v)//根据前驱点画出最短路径
	{
		line(P, Point(local[t].x, local[t].y), Point(local[route[t]].x, local[route[t]].y), Scalar(0, 0, 255), 5, CV_AA);
		imshow("out", P);
		waitKey(20);
		t = route[t];
	}
	imwrite("Dijkstra.png", P);
}
int main()
{
	startdata();
	FILE *fp; int cost[15][15];
	fopen_s(&fp, "input.txt", "r");
	int i = 0, sum = 0;
	while (!feof(fp))
	{
		fscanf_s(fp, "%d %d %d\n", &a[i], &b[i], &c[i]);
		i++; sum++;
	}
	fclose(fp);
	for (i = 0; i < sum; i++)
	{
		Point s;
		circle(P, Point(local[a[i]].x, local[a[i]].y), 40, Scalar(color[a[i]].r, color[a[i]].g, color[a[i]].b), -1);
		circle(P, Point(local[b[i]].x, local[b[i]].y), 40, Scalar(color[b[i]].r, color[b[i]].g, color[b[i]].b), -1);
		line(P, Point(local[a[i]].x, local[a[i]].y), Point(local[b[i]].x, local[b[i]].y), Scalar(0, 0, 0), 5, CV_AA);
		imshow("out", P);
		waitKey(20);
	}
	for (i = 0; i < 15; i++)
		for (int j = 0; j < 15; j++)
		{
			cost[i][j] = MAX_DATA;
		}
	for (i = 0; i < sum; i++)
	{
		cost[a[i]][b[i]] = c[i];
	}
	Dijkstra(1,10, cost, 10);
	for (i = 1; i <= 10; i++)
		printf("%d ", distances[i]);
}

猜你喜欢

转载自blog.csdn.net/youtiankeng/article/details/90349236