您的位置:首页 > 其它

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;
}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: