鄰接表實現dijkstra演算法
阿新 • • 發佈:2019-01-05
先放程式碼:
#include <bits/stdc++.h> using namespace std; #define edgeN 5000005 #define pointN 1000005 #define infinity 2147483647 int pointnum,edgenum,startpoint,cnt(0),dis[pointN],vis[pointN],head[pointN]; struct node{ int distance_to_presentpoint,present_point; inline bool operator <(const node &x) const{ return distance_to_presentpoint > x.present_point; } }; priority_queue<node>q; //we usually use "pair< , >" here,why we use struct is to help us to understand the processes. struct Edge{ int from,to,dis,next; //"to" is the end spot of the edge. //"next" is the edge after the present one. }edge[edgeN]; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') if(ch=='-')f=-1,ch=getchar(); while(ch>='0'&&ch<'9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); return x*f; } inline void add_edge(int from,int to,int dis){ edge[++cnt].from=from;//record the start spot of this edge. edge[cnt].to=to;//record the end spot of this edge. edge[cnt].dis=dis;//record the length of this edge. edge[cnt].next=head[from];//record the next edge of this one. head[from]=cnt;//put this edge into the head array. } inline void dijkstra(){ for(int i=1;i<=pointnum;i++) dis[i]=infinity; dis[startpoint]=0; /*super important*/q.push((node){0,startpoint}); while(!q.empty()){ //save the top of the heap(the shortest edge in the heap)and pop it off node temp=q.top(); q.pop(); int nowposition=temp.present_point; //if it hasn't been visited, visit it if(vis[nowposition]==1) continue; vis[nowposition]=1; for(int i=head[nowposition];i;i=edge[i].next){ //search for all the edge of the top of the heap int nextpoint=edge[i].to; if(dis[nextpoint]>dis[nowposition]+edge[i].dis){ dis[nextpoint]=dis[nowposition]+edge[i].dis; q.push((node){dis[nextpoint],nextpoint});//push the next point into the queue } } } } int main(){ pointnum=read();edgenum=read();startpoint=read(); for(int i=1,frompoint,topoint,distance;i<=edgenum;i++){ frompoint=read();topoint=read();distance=read(); add_edge(frompoint,topoint,distance); } dijkstra(); for(int i=1;i<=pointnum;i++){ if(dis[i]!=infinity) printf("to point %d the shortest distance is %d\n",i,dis[i]); printf("there is no way to point %d\n",i); } return 0; }
-
這是一種稍有缺陷的求單元最短路問題的常用演算法,它可以求得每一個點到起點間的(當然肯定得是有通路的點)最小距離。
-
它的主要思想是從起點開始,對每一個點的出邊進行比較,然後選擇出邊邊權值最小的目標點入隊並開始下一輪擴充套件。核心思想:貪心演算法
-
其主要的缺陷是如果遇到兩點間邊權為負值時會出錯(這一點Bellman-Ford可以完美解決),這一點需要注意。
-
其時間複雜度為O(n^2),通過優先佇列(priority_queue)的優化後可以達到O(mlongn)。
-
上面的模板就是使用了堆優化的模板。並使用了鄰接表儲存,能更方便地處理資料較大的時候的空間問題,如果要用鄰接矩陣儲存,則部分程式碼如下:
//令鄰接矩陣名為f,即:f[][]; //需要用到的陣列有:bool vis[]/*標記點有沒有走到過(入隊過)*/;int dis[]/*記錄每個點到起點的距離,在最開始時,除了直接與起點相連的以外,其他點的dis都為極大值*/; //需要有的變數有:minn/*記錄最小值*/,inf/*這個應該為const int,即定義的最大值,一般為0x3f3f3f3f*/,position/*當前在哪個點*/; int Dijkstra(int start_point){ //初始化; memset(vis,false,sizeof(vis); for(int i=1;i<=點的總數;i++){ dis[i]=inf; } vis[start]=true;dis[start]=0;/*起點到自己的距離為0*/; for(int i=1;i<=點的總數;i++){//初始化起點及與其相連的點; dis[i]=f[start][i]; } for(int i=1;i<=點的總數-1;i++){//由於起點為已知,故所需要遍歷的點的個數為總數減一; minn=inf; for(int j=1;j<=點的總數;j++){//選擇入隊哪一個與這個點相連的點; if(!vis[j]&&minn>dis[j]){ minn=dis[j]; position=j; } } vis[position]=true;//將擴充套件的點標記為已經走過; for(int j=1;j<=點的總數;j++){//由於新擴展出了點,更新dis[]的值; if(!vis[j]) dis[j]=min(dis[j],dis[position]+f[position][j]); } } return dis[n]; }
文章原創,請勿抄襲