使用优先队列的 Dijkstra 算法
用优先队列(堆)实现的Dijkstra算法,最短路问题中的正权图适用,对于稠密图计算比较优秀。
为了方便起见,我把pair<int, int>定义一个pii类型,并且定义了一个二元的优先队列,first代表起始节点到此节点的距离,second表示该节点的编号。存储图的方式我采用了指针实现的邻接表。
这份代码的核心代码不多,只有20多行,STL虽然用了vector、priority_queue、pair,但是相信没有-o2的优化下效率还是有保证的,可能pair会稍微慢一点。
#include <cstdio>
#include <cstring>
#include <utility>
#include <queue>
using namespace std;
#define maxn 10008
#define INF 10000008
typedef struct G_NODE
{
int u, v, w;
struct G_NODE *next;
} Gnode;
int n, m, d[maxn];
Gnode *a[maxn];
void add_edge(int x, int y, int c)
{
Gnode *p = new Gnode;
p->u = x;
p->v = y;
p->w = c;
p->next = a[x]->next;
a[x]->next = p;
}
void init_g()
{
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i)
{
a[i] = new Gnode;
a[i]->next = NULL;
}
for (int i = 0; i < m; ++i)
{
int x, y, c;
scanf("%d %d %d", &x, &y, &c);
add_edge(x, y, c);
add_edge(y, x, c);
}
}
typedef pair<int, int> pii;
priority_queue<pii, vector<pii>, greater<pii> > q;
bool done[maxn];
void dijkstra(int s)
{
Gnode *p;
memset(done, false, sizeof(done));
for (int i = 1; i <= n; ++i)
d[i] = (i == s ? 0 : INF);
q.push(make_pair(d[s], s));
while (!q.empty())
{
pii u = q.top();
q.pop();
int x = u.second;
if (done[x])
continue;
for (p = a[x]->next; p; p = p->next) if (d[p->v] > d[x] + p->w)
{
d[p->v] = d[x] + p->w;
q.push(make_pair(d[p->v], p->v));
}
}
}
int main()
{
freopen("g.in", "r", stdin);
freopen("g.out", "w", stdout);
init_g();
dijkstra(1);
for (int i = 1; i <= n; ++i)
printf("%d ", d[i]);
printf("\n");
return 0;
}