堆(優先佇列)優化dijkstra(鄰接矩陣)
阿新 • • 發佈:2018-12-30
上篇部落格大家學習了最短路的兩種基本演算法,忘了告訴大家,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]);
}
下次,我將發表關於最小生成樹演算法的部落格,請大家繼續關注,靴靴。。。。