使用优先队列的 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;
}

posted @ 2012-11-05 20:08  梓涵VV  阅读(1142)  评论(0编辑  收藏  举报