1. 程式人生 > 其它 >dijkstra + 鏈式前向星 + 優先佇列

dijkstra + 鏈式前向星 + 優先佇列

#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1005;
const int M = 2*10005;
const int INF = 1e8;
int dist[N],head[N];
bool flag[N]={0};
typedef pair<int,int> pii;
int n, m, cnt = 0;

struct Edge{  // 建立 邊 的結構體 
    int
to, w, next; }edge[M]; void add_edge(int u, int v, int w) { // 鏈式前向星 (靜態鏈式鄰接表) 頭插法 edge[cnt].to = v; // to 表示 其終點 edge[cnt].w = w; // w 表示其 權值 edge[cnt].next = head[u]; // next 表示 以 u 為起點的上一條邊的編號 head[u] = cnt ++; // 更新以 u 為起點的邊的編號 cnt 表示編號 } void dijkstra(int u) { // 優先佇列優化 相當於 把之前的每次找最小距離的步驟 用優先佇列直接找出來了
priority_queue< pii, vector<pii>, greater<pii> > q; // 優先佇列 以 pii 的 first 大小(若相等,則比較second)升序排列 for (int i=1; i<=n; i++) dist[i] = INF; // 初始化 q.push({dist[u],u}); // 將 dist[u] u 組成的 pii 放入 q 中 dist[u] = 0; // 自己到自己的 距離初始化為 0 while (!q.empty()) { pii it = q.top(); q.pop();
int st = it.second; // st 表示該點 if (flag[st]) continue; // flag[st] = 1 表示該 點已找到最短距離 continue 無需再重複處理 flag[st] = 1; // 將其標記為 1 說明 已經處理過 for (int i=head[st]; i!=-1; i=edge[i].next) { // 遍歷該點的 連線邊 i 為 其編號 int j = edge[i].to; // j 為 以 st 為起點的邊的 終點 if (!flag[j] && dist[j] > dist[st] + edge[i].w) { // 若其未被標記 且 由源點到j的距離 大於 由源點到st的距離 + 以st為起點的邊的權值 則更新 dist[j] dist[j] = dist[st] + edge[i].w; q.push({dist[j],j}); // 將其 加入 優先佇列 q 中 } } } } int main(){ int u,v,w,a,b; while (cin >> n >> m >> u >> v) { memset(head,-1,sizeof(head)); memset(dist,INF,sizeof(head)); memset(flag,0,sizeof(flag)); while (m--) { cin >> a >> b >> w; add_edge(a,b,w); add_edge(b,a,w); // 無向邊 } dijkstra(u); if (dist[v] == INF) cout << -1 << endl; else cout << dist[v] << endl; } return 0; }