POJ 2387 Til the Cows Come Home 单源最短路(Dijkstra算法 堆优化)

POJ 2387 Til the Cows Come Home 单源最短路(Dijkstra算法 堆优化)
题目大意:求图上单点到单点之间的最短路。
题目分析:之前我们在同一道问题上分析过了单源最短路问题的 Dijkstra算法。
使用邻接矩阵实现的Dijkstra算法的时间复杂度是O(|V|^2)。使用邻接表的话,更新最短距离只需要更新每一条边即可,因此这部分的时间复杂度是O(|E|)。但是每次要枚举所有的顶点来查找下一个使用的顶点,因此最终复杂度还是O(|V|^2)。在|E|比较小时,大部分经历放在了查找下一次要是用的顶点上,因此需要使用合适的数据结构对其进行优化。
需要优化的是数值的插入(更新)和取出最小值两个操作,因此使用堆就可以了。把每个顶点当前的最短距离用堆维护,在更新最短距离时,把对应的元素往根的方向移动以满足堆的性质。而每次从堆中取出的最小值就是下一次要使用的顶点。这样堆中元素共有O(|V|)个,更新和取出数值的操作有O(|E|)次,因此整个算法的复杂度是O(|E|log(V))
#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>
using  namespace std;
#define INF (1<<29)
const  int maxn = 1010;

typedef pair< intint> P;  // first是最短距离,second是顶点的编号
int V, dist[maxn];
vector<P> G[maxn];

void dijkstra( int s) {
     // 通过指定greater<P>参数,堆按照first从小到大的顺序取出值
    priority_queue<P, vector<P>, greater<P> > que;
    fill(dist, dist + V , INF);
    dist[s] = 0;
     while(!que.empty()) que.pop();
    que.push(P(0, s));
     while(!que.empty()) {
        P p = que.top(); que.pop();
         int u = p.second;
         if(dist[u] < p.first)  continue;
         int sz = G[u].size();
         for( int i=0;i<sz;i++) {
             int to = G[u][i].second;
             int cost = G[u][i].first;
             if(dist[to] > dist[u] + cost) {
                dist[to] = dist[u] + cost;
                que.push(P(dist[to], to));
            }
        }
    }
}

int main() {
     int m;
    scanf("%d%d" , &m, &V);
     for( int i=0;i<V;i++) G[i].clear();
     for( int i=0;i<m;i++) {
         int from, to, cost;
        scanf("%d%d%d" , &from, &to, &cost);
        from --; to --;
        G[from].push_back(P(cost, to));
        G[to].push_back(P(cost, from));
    }
    dijkstra(0);
    printf("%d\n", dist[V-1]);
     return 0;
}

你可能感兴趣的:(POJ 2387 Til the Cows Come Home 单源最短路(Dijkstra算法 堆优化))