【模板】Dijkstra總結


  Dijkstra算法使用於跑最短路的算法。

算法思想

  假定圖是不帶負權的有向圖或無向圖,采用貪心策略,每次擴展一個距離為最短的點,在以這個點為中間點,更新其他的所有點的距離。當所有邊權都為正時,由於不會存在一個距離更短的沒有擴展過的點,所以以這個點的距離永遠不會再被更新,因而保證了算法的正確性。

算法流程

  • 初始化dist[1] = 0,其余的點時無窮大。
  • 找出一個未被標記的、dist[u]最小的節點u,然后標記節點u。
  • 掃描節點u的所有出邊,若有dist[v] > dist[u] + w[i](v是到達的節點,w是邊權),則使用dist[u] + w[i]更新dist[y]。
  • 重復上述的兩個步驟直到所有點都被標記。

算法優化

  在上述算法過程我們可以在O(n*m)的時間內算出答案,主要問題在於找出節點u,我們可以利用堆對dist數組進行維護從而使獲得最大值的時間從O(n)變為O(1),但是在維護過程中我們仍然需要O(log(n))的時間來維護。所以我們可在O(mlog(n))的時間內完成最短路。

  值得注意的是,在我們每次更新的時候,優先隊列不支持更改操作,即我們每次更改dist實際上是加入了一個新的節點去維護dist,所以,我們在調取到之前的dist時要選擇直接跳過,否則會直接TLE飛起來。

算法模板(洛谷P4779)

#include<bits/stdc++.h>
using namespace std;
int head[100001],ne[200001],to[200001],w[200001],edgenum=0;
int dis[100001];
bool vis[100001];
int inf;
struct node{
    int pos,val;
    bool operator <(const node &a)const {return a.val<val;}
};
priority_queue<node> que;
inline void addedge(int f,int t,int co)
    {
        ne[++edgenum]=head[f];
        head[f]=edgenum;
        to[edgenum]=t;
        w[edgenum]=co;
    }

inline int read()
    {
        int x = 0, w = 0; char ch = getchar();
        for(;!isdigit(ch);w |= (ch == '-'), ch = getchar());
        for(;isdigit(ch);x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar());
        return w ? -x : x;
    }

inline node make_node(int x, int y)
    {
        node a;
        a.pos = x, a.val = y;
        return a;
    }

void Dijkstra(int s)
    {
        memset(dis,0x3f,sizeof(dis));
       // inf = dis[0];
        dis[s]=0;
        que.push(make_node(s, dis[s]));
        while(!que.empty())
            {
                node x=que.top();que.pop();
                int u = x.pos;
                if(x.val > dis[u]) continue; //這一步就相當於是刪除了那些不夠優的節點
                vis[u]=true;
                for(int i=head[u];i;i=ne[i])
                    {
                        int v=to[i];
                        if(vis[v])    continue;
                        if(dis[v]>w[i]+dis[u])
                            {
                                dis[v]=w[i] + dis[u];
                                que.push(make_node(v, dis[v]));
                            }
                    }
            }
    }
int main()
{
    int n = read(),m = read(),s = read(),x,y,l;
    for(int i=1;i<=m;i++)
        {
            //scanf("%d%d%d",&x,&y,&l);
            x = read(), y = read(), l = read();
            addedge(x,y,l);
        }
    Dijkstra(s);
    for(int i=1;i<=n;i++)  printf("%d ",dis[i]);
    printf("\n");
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM