最短路-Dijkstra算法

来源:互联网 发布:linux 解压war包 编辑:程序博客网 时间:2024/06/06 03:07

对有向图,无向图均有效。要求,权值为正。

贪心。每次取距离s最近的点,来更新其他点。

BFS。将权值看成单位长度的路径之和,最近的点即BFS最先达到的点。

定义delta(u,v),若u,v不可达,值为无穷。若u,v可达,则delta(u,v) 即u,v间最短距离。

松弛操作:

RELAX(u,v,w)

 if d[u] > d[v] + w(u,v)

then d[u] = d[v] + w(u,v)

parent[v] = u


#include <iostream>

#include <cstdio>

#include <vector>

#include <queue>

using namespacestd;

const int maxn =10005;

const int INF =1 <<20;

struct edge{

    int v,w;

};

typedef pair<int,int> pr;// delta[i] i

int d[maxn];//初始化为无限,依次更新,至达到delta(u)。//类似并查集中f[x] 和 find(int x)的关系,需要更新。//不同的是并查集find(x)需要通过f[x]来得到,f[x]的值可能是该树根节点,也可能只是该树x节点的某个祖先。而d[u]一开始被初始化为INF,通过遍历更新,可以证明,最后可以达到真实值,即delta(u),而在中间过程,不一定为最小值delta(u)

void dijkstra(int s,int n,vector<edge> mp[maxn])

{

    for (int i =1; i <= n; i ++) {

        d[i] =INF;

    }

    d[s] =0;

    

    priority_queue<pr,vector<pr>,greater<pr> >pq;

    pq.push(pr{d[s],s} );

    while (!pq.empty()) {

        pr p = pq.top();

        pq.pop();

        int th = p.second;

        if (d[th] >= p.first) {//如果此时d[i]中存的值,不小于,真实i点到起点到距离,即delta(s,i),那么就更新

            for (int i =0; i < mp[th].size() ; i ++) {

                edge &e = mp[th][i];

                if (d[e.v] >d[th] + e.w) {

                    d[e.v] =d[th] + e.w;

                    pq.push(pr {d[e.v],e.v});//bfs

                }

            }

        }

        

    }

}

int main()

{

    int n,m;

    while (cin >> n >> m) {

        if (n ==0 && m ==0) {

            return0;

        }

        int a,b,c;

        vector<edge> mp[maxn];// u v w


        for (int i =0; i < m; i ++) {

            scanf("%d %d %d",&a,&b,&c);

            mp[a].push_back(edge{b,c});

            mp[b].push_back(edge{a,c});

        }

        dijkstra(1, n, mp);

        cout <<d[n] <<endl;

    }

    return0;

}






0 0
原创粉丝点击