程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hdoj1874 (優先隊列+Dijkstra),hdoj1874dijkstra

hdoj1874 (優先隊列+Dijkstra),hdoj1874dijkstra

編輯:C++入門知識

hdoj1874 (優先隊列+Dijkstra),hdoj1874dijkstra


hdoj1874

分析: 
一看題目, 就是求最短路, 這道題用的是Dijkstra+優先隊列。先說一下Dijkstra算法:每次擴展一個距離最短的節點, 更新與其相鄰點的距離。 當所有邊權都為正時, 由於不會存在一個距離更短的沒有擴展的點,所以這個點的距離不會在改變, 保證了算法的正確性。

算法步驟如下: 
G={V,E} 
1. 初始時令 S={V0},T=V-S={其余頂點},T中頂點對應的距離值 
  若存在〈V0,V〉,d(V0,Vi)為〈V0,Vi〉弧上的權值 
  若不存在〈V0,Vi〉,d(V0,Vi)為∞ 
2. 從T中選取一個與S中頂點有關聯邊且權值最小的頂點W,加入到S中 
3. 對其余T中頂點的距離值進行修改:若加進W作中間頂點,從V0到Vi的距離值縮短,則修改此距離值 
重復上述步驟2、3,直到S中包含所有頂點,即W=Vi為止。

偽代碼:

將所有節點狀態初始化(標記為未計算) 
設起始點s, d[s] = 0; 其他節點d[i] = MAX; 
循環n次 

  在所有未標記的節點中, 選出d值最小的節點x; 
  標記節點x; 
  對於所有從x節點出發的所有邊(x, y), 更新d[y] = min(d[y], d[x] + w(x, y)); 
}

對應代碼:

memset(v, 0, sizeof(v));
for(int i = 0; i < n; i++)
    d[i] = 10e8;
d[s] = 0;
for(int i = 1; i < n; i++)
{
    int mi = 10e8;
    for(int j = 1; j < n; j++)
    {
        if(v[j] == 0 && d[j] < mi)
            mi = d[j];
        v[j] = 1;
        for(int k = 0; k < n; k++)
            if(d[k] < d[j] + w[j][k])
                d[k] = d[j] + w[j][k];
    }
}

程序的復雜度為n方, 每一次都要求所有d中的最小值。 然而STL中的優先隊列priority_queue正好解決了這一問題。

#include<iostream> #include<cstdio> #include<string.h> #include<math.h> #include<algorithm> #include<queue> #include<vector> using namespace std; int n, m, s, t, v[1005]; double d[1005]; struct edge { int v; double d; }e[1005]; struct node//存儲點的信息, 起始點到x節點的最短距離d. { int x; double d; }no[1005]; bool operator< (node a, node b) { return a.d > b.d; } vector<edge> vec[1005]; double ac(int x) { memset(v, 0, sizeof(v)); priority_queue<node> q; node tem; tem.x = s; tem.d = 0; q.push(tem);//將起始點加入隊列 while(!q.empty()) { node tem = q.top();//取出d值最小的 q.pop(); int x = tem.x; if(x == t) return tem.d; if(v[x] == 1) continue; v[x] = 1; for(int i = 0; i < vec[x].size(); i++)//更新從tem.x出發的所有邊(x,y),d[y] = min(d[y], d[x]+w[x][y]) { int y = vec[x][i].v; if(d[y] > (tem.d + vec[x][i].d)) { d[y] = tem.d + vec[x][i].d; node node1; node1.x = y; node1.d = d[y]; q.push(node1); } } } return -1; } int main() { while(scanf("%d%d", &n, &m) != EOF) { for(int i = 0; i <= n; i++) vec[i].clear(); for(int i = 0; i <= n; i++) d[i] = 10e8; for(int i = 1; i <= m; i++) { int x, y, w; scanf("%d%d%d", &x, &y, &w); edge e; e.v = y; e.d = w; vec[x].push_back(e);//用vector存邊, e.v = x; vec[y].push_back(e); } scanf("%d%d", &s, &t); d[s] = 0; double ans = ac(s); if(ans == -1) printf("-1\n"); else printf("%.0lf\n", ans); } return 0; } View Code

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved