Dijkstra(迪杰斯特拉)算法是一种经典的求单源最短路的算法,大体上就是利用已经找到的点的最短路去推其他点的最短路。

我们先将图中的点分为两部分:

S:已经找到最短路的点

T:图G - S,剩下的点

具体过程如下:

  • 将dis数组初始化为INF,源点s,dis[s] = 0,s点加入S集,s点为当前点
  • 重复以下步骤:
  • 遍历当前点的子点,如果当前点的子点dis值 > dis[当前点]+其之间边的边权,将子点dis值更新为dis[当前点]+其之间边的边权
  • 在T集中找出一个dis值最小的点移入S集,并将其作为当前点
  • 直到T集为空时,结束

经过上述步骤之后,dis数组内的值便是每一点到源点的最短路值。

示例代码(kuangbin模板):

const int MAXN=1010;
#define typec int
const typec INF=0x3f3f3f3f;//防止后面溢出,这个不能太大
bool vis[MAXN];
int pre[MAXN];
void Dijkstra(typec cost[][MAXN], typec lowcost[], int n,int beg){
    for(int i=0;i<n;i++){
        lowcost[i]=INF; vis[i]=false; pre[i]=−1;
    }
    lowcost[beg]=0;
    for(int j=0;j<n;j++){
        int k=−1;
        int Min=INF;
        for(int i=0;i<n;i++)
            if(!vis[i]&&lowcost[i]<Min){
                Min=lowcost[i];
                k=i;
            }
        if(k==−1)break;
        vis[k]=true;
        for(int i=0;i<n;i++)
            if(!vis[i]&&lowcost[k]+cost[k][i]<lowcost[i]){
                lowcost[i]=lowcost[k]+cost[k][i];
                pre[i]=k;
            }
    }
}

算法中每次寻找T集中dis值最小的点的复杂度为O(n),我们可以用堆(heap)来优化这一过程,使其复杂度降到O(logn),这样总体复杂度降到O(nlogn)。

示例代码(kuangbin模板):

const int INF=0x3f3f3f3f;
const int MAXN=1000010;
struct qnode{
    int v;
    int c;
    qnode(int _v=0,int _c=0):v(_v),c(_c){}
    bool operator <(const qnode &r)const{
        return c>r.c;
    }
};
struct Edge{
    int v,cost;
    Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
};
vector<Edge>E[MAXN];
bool vis[MAXN];
int dist[MAXN];
//点的编号从 1 开始
void Dijkstra(int n,int start){
    memset(vis,false,sizeof(vis));
    for(int i=1;i<=n;i++) dist[i]=INF;
    priority_queue<qnode>que;
    while(!que.empty())que.pop();
    dist[start]=0;
    que.push(qnode(start,0));
    qnode tmp;
    while(!que.empty()){
        tmp=que.top();
        que.pop();
        int u=tmp.v;
        if(vis[u])continue;
        vis[u]=true;
        for(int i=0;i<E[u].size();i++){
            int v=E[tmp.v][i].v;
            int cost=E[u][i].cost;
            if(!vis[v]&&dist[v]>dist[u]+cost){
                dist[v]=dist[u]+cost;
                que.push(qnode(v,dist[v]));
            }
        }
    }
}
void addedge(int u,int v,int w){
    E[u].push_back(Edge(v,w));
}