Dijkstra求单源最短路径
2018-01-09 22:16
363 查看
思路:Dijkstra求解带权有向图的单源最短路径问题。与Bellman-Ford算法的区别是要求图中没有负的权值边。在这种情况下Dijkstra算法通常有比较好的复杂度。特别是使用堆以后。算法维护一个点集S,该集合中的结点的最短路径已经求出,算法重复从结点集V-S中选择最短路径估计最小的结点,将其加入S中,并该结点出发的所有边进行松弛。
代码:
// dijkstra.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <queue>
#include <fstream>
#include <stack>
#define MAX 100
#define INF 1000000
#define DIS(a) (dis[a])
using std::cin;
using std::cout;
using std::endl;
using std::cerr;
using std::priority_queue;
using std::ifstream;
using std::stack;
typedef struct Edge {
int u;
int v;
int val;
};
class mycomparison
{
int dis[MAX];
public:
mycomparison(int a[MAX], int n)
{
for (int i = 0; i < n; i++)
dis[i] = a[i];
}
bool operator() (const int &a, const int &b) const
{
return dis[a] > dis[b];
}
};
//对边(u,v)的松弛操作
void relax(int u, int v, int pre[MAX], int dis[MAX], int a[MAX][MAX])
{
if (dis[v] > dis[u] + a[u][v])
{
dis[v] = dis[u] + a[u][v];
pre[v] = u;
}
}
void dijkstra(int a[MAX][MAX], int vertex_num, int edge_num, int dis[MAX], int pre[MAX])
{
typedef priority_queue<int, std::vector<int>, mycomparison> mypq_type;
mypq_type Q(mycomparison(dis, vertex_num));
for (int i = 0; i < vertex_num; i++) //初始化优先级队列
Q.push(i);
while (!Q.empty())
{
int temp = Q.top();
Q.pop();
for (int i = 0; i < vertex_num; i++)
{
if (a[temp][i] != INF)
relax(temp, i, pre, dis, a);
}
}
}
//重构路径
void reconstruct(int i, int pre[MAX], stack<int> &s)
{
if (pre[i] == -1) //边界情况,重构源结点
{
s.push(i);
return;
}
s.push(i); //加入本结点
while (pre[i] != -1)
{
s.push(pre[i]);
i = pre[i];
}
}
int main()
{
ifstream in;
in.open("dijkstra测试数据.txt");
int vertex_num, edge_num; //点数,边数
in >> vertex_num >> edge_num;
int a[MAX][MAX];
for (int i = 0; i < vertex_num; i++) //初始化邻接矩阵
for (int j = 0; j < vertex_num; j++)
a[i][j] = INF;
int u, v, val;
for (int i = 0; i < edge_num; i++)
{
in >> u >> v >> val;
a[u][v] = val;
}
int dis[MAX]; //最短路径权重
for (int i = 0; i < vertex_num; i++)
dis[i] = INF;
int pre[MAX]; //前驱结点
for (int i = 0; i < vertex_num; i++)
pre[i] = -1;
dis[0] = 0;
dijkstra(a, vertex_num, edge_num, dis, pre);
stack<int> s; //用于重构路径
for (int i = 0; i < vertex_num; i++)
{
cout << dis[i] << endl << "route: ";
reconstruct(i, pre, s);
while (!s.empty())
{
int temp = s.top();
cout << temp << " ";
s.pop();
}
cout << endl;
}
system("pause");
return 0;
}
代码:
// dijkstra.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <queue>
#include <fstream>
#include <stack>
#define MAX 100
#define INF 1000000
#define DIS(a) (dis[a])
using std::cin;
using std::cout;
using std::endl;
using std::cerr;
using std::priority_queue;
using std::ifstream;
using std::stack;
typedef struct Edge {
int u;
int v;
int val;
};
class mycomparison
{
int dis[MAX];
public:
mycomparison(int a[MAX], int n)
{
for (int i = 0; i < n; i++)
dis[i] = a[i];
}
bool operator() (const int &a, const int &b) const
{
return dis[a] > dis[b];
}
};
//对边(u,v)的松弛操作
void relax(int u, int v, int pre[MAX], int dis[MAX], int a[MAX][MAX])
{
if (dis[v] > dis[u] + a[u][v])
{
dis[v] = dis[u] + a[u][v];
pre[v] = u;
}
}
void dijkstra(int a[MAX][MAX], int vertex_num, int edge_num, int dis[MAX], int pre[MAX])
{
typedef priority_queue<int, std::vector<int>, mycomparison> mypq_type;
mypq_type Q(mycomparison(dis, vertex_num));
for (int i = 0; i < vertex_num; i++) //初始化优先级队列
Q.push(i);
while (!Q.empty())
{
int temp = Q.top();
Q.pop();
for (int i = 0; i < vertex_num; i++)
{
if (a[temp][i] != INF)
relax(temp, i, pre, dis, a);
}
}
}
//重构路径
void reconstruct(int i, int pre[MAX], stack<int> &s)
{
if (pre[i] == -1) //边界情况,重构源结点
{
s.push(i);
return;
}
s.push(i); //加入本结点
while (pre[i] != -1)
{
s.push(pre[i]);
i = pre[i];
}
}
int main()
{
ifstream in;
in.open("dijkstra测试数据.txt");
int vertex_num, edge_num; //点数,边数
in >> vertex_num >> edge_num;
int a[MAX][MAX];
for (int i = 0; i < vertex_num; i++) //初始化邻接矩阵
for (int j = 0; j < vertex_num; j++)
a[i][j] = INF;
int u, v, val;
for (int i = 0; i < edge_num; i++)
{
in >> u >> v >> val;
a[u][v] = val;
}
int dis[MAX]; //最短路径权重
for (int i = 0; i < vertex_num; i++)
dis[i] = INF;
int pre[MAX]; //前驱结点
for (int i = 0; i < vertex_num; i++)
pre[i] = -1;
dis[0] = 0;
dijkstra(a, vertex_num, edge_num, dis, pre);
stack<int> s; //用于重构路径
for (int i = 0; i < vertex_num; i++)
{
cout << dis[i] << endl << "route: ";
reconstruct(i, pre, s);
while (!s.empty())
{
int temp = s.top();
cout << temp << " ";
s.pop();
}
cout << endl;
}
system("pause");
return 0;
}
相关文章推荐
- 算法导论 单源最短路径 Dijkstra
- 单源最短路径——dijkstra
- Dijkstra求单源最短路径(图论基础算法)
- 最短路径 (单源最短路径Dijkstra和任意两点最短路径Floyd) C实现
- Dijkstra---求单源最短路径(贪心算法)
- HDU 2066 一个人的旅行(Dijkstra求特殊点的单源最短路径)
- Dijkstra算法求单源最短路径Java实现
- Spark GraphX之Dijkstra(单源最短路径)、Prime(最小生成树)、FloydWarshall(多源最短路径)
- 数据结构重读——单源最短路径(Dijkstra) 转自酷勤
- 浅析最小生成树和单源最短路径的区别(含Prim、Kruskal、Dijkstra、Bellman-Ford)
- 数据结构与算法--单源最短路径算法之dijkstra
- 单源最短路径--Dijkstra
- 图论算法(二)-最短路径的Dijkstra [ 单源 ] 和Floyd[ 多源 ] 解法(JAVA )
- 【HDU 1874 2544 2066 2112】 Dijkstra单源最短路径专题 —— 优先队列+邻接表/邻接矩阵
- 单源最短路径问题[Dijkstra实现]
- 单源最短路径——Dijkstra
- 贪心算法之单源最短路径Dijkstra
- POJ 1125 Stockbroker Grapevine (Dijkstra求所有点的单源最短路径)
- 贪心算法之Dijkstra单源最短路径问题
- POJ 2387Til the Cows Come Home(最短单源路径)(dijkstra)