dijkstra算法模板

/* solution: 关键是维持一组节点的信息集合S。从源点s到该集合中每个结点的最短路径已经被找到。 算法重复从结点集合V-S中选择最短路径估计最小的点u,将u加入到集合S中,然后对从u出 发的边进行松弛。 note: 1.注意一开始进行dijkstra时候一定要做好初始化工作,确保没有上一组数据的残留。 2.注意为了存储整张图的完整信息,G[u]容器中存储的是与u相邻的边在edges容器中的下标位置。 3.定义了一个结构体heapNode作为优先队列中的数据类型。 4.heapNode中自定义了一个比较器来重载<运算符,以便在优先队列中每次在队列头部的是最小元素。 5.注意比较器中 return d > rhs.d;这样子定义的就是最小堆,反之就是最大堆。 6.松弛操作。 date: 2016/4/21 */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;
const int maxn = 100 + 5;
const int INF = 99999999;

struct Edge {
    int u, v, val;
    Edge(int u, int v, int val) : u(u), v(v), val(val) {}
};

struct heapNode {
    int d, u;
    bool operator < (const heapNode & rhs) const {
        return d > rhs.d;
    }
};

struct Dijkstra {
    int n, m;   //分别是节点数目以及边的数目
    vector<Edge> edges;
    vector<int> G[maxn];
    bool vis[maxn];     //一个节点是否访问过
    int d[maxn];    //每个节点到开始节点的最小路径长度
    int p[maxn];    //记录每个最短路径上的节点的父节点

    void initial(int n) {   //初始化
        this->n = n;
        for(int i = 0; i < n; i++)  G[i].clear();
        edges.clear();
    }

    void addEdge(int u, int v, int val) {   //添加边
        edges.push_back(Edge(u, v, val));
        int m = edges.size();
        G[u].push_back(m-1);
    }

    void dijkstra(int start) {  //主算法
        priority_queue<heapNode> q;
        for(int i = 0; i < n; i++)  d[i] = INF;
        d[start] = 0;
        memset(vis, 0, sizeof(vis));
        q.push((heapNode) {0, start});  //把开始节点压入优先队列

        while(!q.empty()) {
            heapNode x = q.top();   q.pop();
            int u = x.u;
            if(vis[u])  continue;
            vis[u] = true;
            for(int i = 0; i < G[u].size(); i++) {
                Edge& e = edges[G[u][i]];
                if(d[e.v] > d[u] + e.val) {     //该if判断里面的操作被称为“松弛操作”
                    d[e.v] = d[u] + e.val;
                    p[e.v] = G[u][i];
                    q.push((heapNode) {d[e.v], e.v});
                }
            }
        }
    }
};

int main()
{

    return 0;
}

你可能感兴趣的:(dijkstra算法模板)