利用小根堆优化每次查找dis数组最短距离的复杂度
只要看过小根堆,这个代码并不难,但有细节需要处理
我是手写堆,但用priority_queue更简单
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000;
int f[maxn][maxn];
int vis[maxn];
int d[maxn];
const int inf=999999;
int len;
struct dot{
int xu;
int va;
}dis[maxn];//设置结构体,保存节点的序号和值
//手写堆的push操作
void push(dot n){
dis[++len]=n;
int son=len;
while(son/2){
if(dis[son/2].va>dis[son].va){
swap(dis[son/2],dis[son]);
son/=2;
}
else break;
}
}
//pop操作
dot pop(){
dot tp=dis[1];
swap(dis[1],dis[len--]);
int pa=1,son=2;
while(son<=len){
if(dis[son].va>dis[son+1].va&&son<len){
son++;//别忘了判断son+1是否超过len
}
if(dis[son].va>dis[pa].va)
break;
swap(dis[son],dis[pa]);
pa=son;
son=pa*2;
}
return tp;
}
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
int x,y,z;
cin>>x>>y>>z;
f[x][y]=f[y][x]=z;
}
fill(d,d+maxn,inf);
push({1,0});
d[1]=0;
while(len){
dot tp=pop();
if(vis[tp.xu])//由于一个点的最短距离会多次改变,
//所以堆中可能会有多个重复节点 ,但每次取出的是最小的,所以被取出一次后,
//后面的重复节点都可以忽略
continue;
vis[tp.xu]=1;
for(int i=1;i<=n;i++){
if(f[tp.xu][i]&&!vis[i]&&d[i]>f[tp.xu][i]+tp.va)
{
push({i,f[tp.xu][i]+tp.va});
d[i]=f[tp.xu][i]+tp.va;//d的值不要忘了改
}
}
}
cout<<d[n];
return 0;
}