上篇博客大家学习了最短路的两种基本算法,忘了告诉大家,floyd可以完成有负权值的最短路,而dijkstra则不行。若要想要更优的进行负权值最短路,请期待我的SPFA详解。
现在开始堆优化dijkstra的讲解。
其实只要理解了dijkstra的本质,这也就不难了,就是把查询最小dis值的过程用堆实现即可。具体代码如下:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int n,num,tree[10000][10],map[1000][1000],book[1000],dis[1000],m,i,j,mini,u;
void swap(int x,int y){//堆操作
int t;
t=tree[x][1];
tree[x][1]=tree[y][1];
tree[y][1]=t;
t=tree[x][2];
tree[x][2]=tree[y][2];
tree[y][2]=t;
}
void siftdown(int i){//堆操作
int t,flag=0;
while (i*2<=n&&flag==0){
t=i;
if (tree[i][1]>tree[i*2][1]) t*=2;
if (i*2+1<=n){
if (tree[t][1]>tree[i*2+1][1]){
t=i*2+1;
}
}
if (i!=t){
swap(i,t);
i=t;
}
else flag=1;
}
}
void build(){//堆操作
int i;
for (i=trunc(n/2);i>=1;--i) siftdown(i);
}
int posh(){
int t;
t=tree[1][1];
tree[1][1]=tree[n][1];
n--;
siftdown(1);
return t;
}
int main(){
scanf("%d%d",&num,&m);
n=num;
for (i=1;i<=n;++i)
for (j=1;j<=n;++j){
i==j?map[i][j]=0:map[i][j]=21474836;
}
for (i=1;i<=m;++i){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
map[x][y]=z;
map[y][x]=z;
}
for (i=1;i<=num;++i){
dis[i]=tree[i][1]=map[1][i];
tree[i][2]=i;
book[i]=0;
}
build();
book[1]=1;
mini=posh();
for (i=1;i<=num-1;++i){
u=tree[1][2];mini=posh();//堆代替for循环
book[u]=1;
for (j=1;j<=num;++j){
if (dis[j]>dis[u]+map[u][j]){
dis[j]=map[u][j]+dis[u];
}
}
}
printf("%d",dis[num]);
}
下次,我将发表关于最小生成树算法的博客,请大家继续关注,靴靴。。。。