Dijkstra + 堆优化

Dijkstra 一般流程


  • 1.初始化dis[start] = 0,dis[start]=0​​,其余节点的dis​值为无穷大.
  • 2.找一个disdis值最小的蓝点x,x,把节点xx变成白点.
  • 3. 遍历xx的所有出边(x,y,z),(x,y,z),若dis[y] > dis[x] + z,dis[y]>dis[x]+z,则令dis[y] = dis[x] + z​
  • 4.重复2,32,3两步,直到所有点都成为白点..
  • 时间复杂度为O(n^2)​


//采用堆优化  #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int Maxn=2e5+5; bool vis[Maxn<<1];//判断是否有经过  const int INF=0x7f7f7f7f; int n,m,s,dis[Maxn]; int head[Maxn<<1],top; struct Edge{int to,next,val,pre;}edge[Maxn<<1]; void addEdge(int u,int v,int val){     edge[++top].to=v;     edge[top].next=head[u];     edge[top].pre;     edge[top].val=val;     head[u]=top; } struct Node{     int dis;//值     int pos;//当前点     Node(int dis, int pos):dis(dis),pos(pos){}//给堆里面加值      bool operator <(const Node &x) const{         return x.dis<dis;//定义堆为小根堆      } }; priority_queue<Node>q;  void Dijkstra(int s){     memset(dis,INF,sizeof(dis)); //初始化为无穷大      dis[s]=0;//刚开始时为 0      q.push((Node){0,s});//存入当前点的值和点的位置      while(!q.empty()){//我们的目的就是直到队列为 空 ,否则就是还有路          Node temp=q.top();//将队头元素记录下来,因为这是值最小的  //        printf("%d ",temp.pos);         //优化了步骤 2          q.pop();         int u=temp.pos;//当前的点的位置         int d=temp.dis;//当前的点距离源点的最短路径          if(vis[u]) continue;//遍历过的话就不用再次遍历         vis[u]=true;         for(int i=head[u];i;i=edge[i].next){             int v=edge[i].to;             if(dis[v]>dis[u]+edge[i].val){//更新                  dis[v]=dis[u]+edge[i].val;                 if(!vis[v]) q.push((Node){dis[v],v});                              }         }      } } int main(){     scanf("%d%d%d",&n,&m,&s);     for(int i=1;i<=m;i++){         int u,v,w;         scanf("%d%d%d",&u,&v,&w);         addEdge(u,v,w);//有向边      }      Dijkstra(s);     for(int i=1;i<=n;i++)             printf("%d ",dis[i]);     return 0; }