Dijkstra + 堆优化

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;
}

 

 

posted @ 2021-08-04 16:11  xwl呀。  阅读(92)  评论(0)    收藏  举报