最短路——Dijkstra算法

解决:单源最短路问题(一个源点到其余所有点的最短路问题)

堆优化复杂度:O(nlogn)

算法思想:可以理解为多米诺骨牌,先到达点t的骨牌有贡献,后到达的骨牌无贡献。利用贪心的思想

步骤:源点s

1:首先将所有的点分为两类,一类是已经找到到源点s的最短路的点S,一类是没有找到T。起初S中只有源点s

2:在s的所有直连邻居中,找到最近的邻居u,u肯定是骨牌最首先到达的,那么记录dis[u]的值,然后再在u的直连邻居中+dis[u]的直连邻居比较,找到最小的值v,记录dis[v],下次再在v的直连邻居中+dis[v]和s的直连邻居以及u的直连邻居+dis[u]中找最小值,如此查找,直到找到所有的结点

const int N=1e5+10;
const int INF=1e9;
struct edge{
    int from,to,w;
    edge(int a,int b,int c){
        from=a,to=b,w=c;
    }
};
struct s_node{
    int id,n_dis;//id:结点号 n_dis:这个结点到起点的一个距离
    s_node(int b,int c) {
        id=b;
        n_dis=c;
    } 
    bool operator<(const struct s_node &a) const{
        return n_dis>a.n_dis;
    }
};
int dis[N];//记录所有结点到源点的最短距离
bool done[N];//true表示已经找到该结点的最短路 
int pre[N];
vector<struct edge> E[N];
int n;
void Print_path(int s,int t){
    if(s==t) {
        cout<<s<<" ";
        return ;
    }
    Print_path(s,pre[t]);
    cout<<t<<" "; 
}
void dijkstra(int s){//s表示源点 
    for(int i=1;i<=n;i++) dis[i]=INF,done[i]=false;
    dis[s]=0;
    priority_queue<struct s_node>q;
    while(!q.empty()){
        s_node u=q.top();q.pop();
        if(done[u.id]) continue;//若是没有这一行,大概率会超时
        done[u.id]=true;
        for(int i=0;i<E[u.id].size();i++){
            struct edge y=E[u.id][i];
            if(done[y.to]) continue;
            if(dis[y.to]>y.w+u.n_dis){
                dis[y.to]=y.w+u.n_dis;
                q.push(s_node(y.to,dis[y.to]));
                pre[y.to]=u.id;
            }
        }
    }
} 

 

posted @ 2020-08-10 09:16  白菜茄子  阅读(172)  评论(0编辑  收藏  举报