一,简介
dijistra算法是求从源点开始u到其他点的最短路径问题。前提条件是带权值的边。权值为正数。
1.将每个点的距离设为无穷大,彼此都不连通。将这些点的集合设为S.
2.另一个集合为V。从源点s开始,距离设为0,放到集合V中。
3.设每条边是<u,v>。则通过dist(v) = min{dis(v),dist(u) + l(u,v)} 进行松弛操作。选取最小代价的点,放到集合V中,直到集合S中的元素被拿光结束。
二,代码
void dijistra1(int u){
int inf = 0x3f3f3f3f;//无穷边
memset(trackPath, -1, sizeof(trackPath));//记录u到其他顶点的最短路径
memset(path, inf, sizeof(path));//记录u到其他顶点的最短路径
memest(rec, false, sizeof(rec));//记录那些点已经计算了,放到了集合V中
path[u] = 0;//自己到自己距离为0
int m;
for(int i = 0; i <= n; i++){
for(int j = 1, m = inf; j <= n; j++){
if(!rec[j] && path[j] < m){
m = path[j];
u = j;
}
}
rec[u] = true;
for(int k = 1; k <= n; k++){
if(!rec[k]){
//松弛操作
path[k] = min(path[k], path[u] + g[u][k]);
trackPath[k] = u;//记录最短路径u到k,k的前驱:可以追踪最短路径的线路
}
}
}
}
堆优化
堆优化的主要思想就是使用一个优先队列(就是每次弹出的元素一定是整个队列中最小的元素)来代替最近距离的查找,用邻接表代替邻接矩阵,这样可以大幅度节约时间开销,就是对下面的代码进行优化,使用优先队列,就不用每次O(n)查找,效率O(nlogn)
for(int j = 1, m = inf; j <= n; j++){
if(!rec[j] && path[j] < m){
m = path[j];
u = j;
}
}
struct Node{
int u, dis;
Node(int u, int dis): u(u), dis(dis){}
bool operator < (const Node& t) const{//重小到大排序
return dis > t.dis;
}
}
void dijistra2(int u){
memset(path, inf, sizeof(path));
memset(rec, false, sizeof(rec));
memset(trackPath, -1, sizeof(trackPath));//记录u到其他顶点的最短路径
path[u] = 0;
priority_queue<Node>q;
q.push(Node(u, 0));
while(q.empty()){
int uu = q.top().u;
q.pop();
if(rec[uu]) continue;
rec[uu] = true;
for(int k = 1; k <= n; k++){
if(!rec[k] && path[k] > path[uu] + g[uu][k]){
path[k] = path[uu] + g[uu][k];
q.push(Node(k, path[k]));
trackPath[k] = uu;
}
}
}
}