dijkstra算法是查找单源最短路径的算法,但它的时间复杂度过高,因此就有了空间换时间的方法,用堆来进行优化,这里只介绍priority_queue()的做法。
废话不多说,代码中讲
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 10000;
int n;
struct node
{
int to, cost;
node (int a, int b): to(a), cost(b) {}
bool operator < (const node &b) const
{
return cost > b.cost;
}
};
vector<node> G[maxn];
int vis[maxn], dis[maxn], pre[maxn];
//标记点有没有被访问过,记录源点到某点的最短距离,记录前驱/路径
void dijkstra(int start)
{
priority_queue<node> que;
memset(vis,.0, sizeof(vis));
memset(dis, INF, sizeof(dis));
memset(pre, INF, sizeof(pre));
dis[start] = 0;
que.push(node(start, 0));
pre[start] = start; //源点没有前驱
while (!que.empty())
{
node front = que.top();
int tempv = front.to;
que.pop();
if (vis[tempv])
{
continue;
}
vis[tempv] = 1;
for (int i=0; i<G[tempv].size(); i++)
{
int p = G[tempv][i].to;
if (!vis[p] && dis[tempv]+G[tempv][i].cost < dis[p])
{
dis[p] = dis[tempv] + G[tempv][i].cost;
pre[p] = tempv; //找前驱的
que.push(node(p, dis[p]));
}
}
}
}
void dth(int d) //查找路径也就是前驱的函数
{
if (d!=pre[d])
{
dth(pre[d]);
}
cout << d+1 << " ";
}
int main()
{
int n, m, s;
cin >> n >> m >> s;
//n为顶点个数,m为边的条数,s为源点
for (int i=0; i<m; i++)
{
int from, to, cost;
cin >> from >> to >> cost;
from--; //顶点是从1开始的但是邻接表得从零开始,所以所有数据都减一
to--;
G[from].push_back(node(to, cost));
G[to].push_back(node(from, cost));
}
dijkstra(s-1);
for (int i=0; i<n; i++)
{
cout << dis[i] << " ";
}
cout << endl;
cout << dis[n-1] << endl; //这里的n-1是任意的我只是为了方便才这么写的
dth(n-1);
return 0;
}