#include<iostream>
using namespace std;
const int size = 100;
const int inf = 5000; //兩點距離上界
//第一組測試參數
const int n = 6; //圖頂點個數加1
int prev[n]; //圖的前驅頂點
int dist[] = {0,0,5000,5000,5000,5000}; //最短距離數組
int c[n][n] = {{0,0,0,0,0,0},{0,0,2,3,5000,5000}, //圖的鄰接矩陣
{0,5000,0,1,2,5000},{0,5000,5000,0,9,2},
{0,5000,5000,5000,0,2},{0,5000,5000,5000,5000,0}};
/*
//第二組測試參數
const int n = 5; //圖頂點個數加1
int prev[n]; //圖的前驅頂點
int dist[] = {0,0,5000,5000,5000};
int c[][n] = {{0,0,0,0,0},{0,0,2,3,5000},{0,5000,0,1,2},{0,5000,5000,0,9},{0,5000,5000,5000,0}};
*/
class MinHeapNode{
public :
int i; //頂點編號
int length; //當前路長
};
//迴圈隊列
class CirQueue{
private:
int front,rear;
MinHeapNode data[size];
public:
CirQueue(){
front = rear = 0;
}
//元素入隊操作
void queryIn(MinHeapNode e){
if((rear +1)%size != front){
rear = (rear+1)%size; //隊尾指標在迴圈意義下加1
data[rear] = e; //在隊尾插入元素
}
}
//元素出隊操作
MinHeapNode queryOut(){
if(rear != front){
front = (front+1)%size; //隊列在迴圈意義下加1
return data[front];
}
}
//讀取隊頭元素,但不出隊
MinHeapNode getQuery(){
if(rear != front){
return data[(front+1)%size];
}
}
//判斷隊列是否為空白
bool empty(){
return front == rear;
}
//判斷隊列是否為滿
bool full(){
return (rear +1)%size == front;
}
};//CirQueue結束
//圖的表示
class Graph{
public:
/**
* 單源最短路徑問題的優先隊列式分支限界法
*/
void shortestPath(int v){
//建立隊列
CirQueue qq;
//定義源為初始擴充結點
MinHeapNode e;
e.i = v;
e.length = 0;
dist[v] = 0;
qq.queryIn(e);
//搜尋問題的解空間
while(true){
for(int j = 1;j<n;j++){
if(j>=n){
break;
}
MinHeapNode m = qq.getQuery();
if((c[m.i][j]<inf)&&(m.length + c[m.i][j] < dist[j])){
//頂點i到頂點j可達,且滿足控制約束
dist[j] = m.length + c[m.i][j];
prev[j] = m.i;
//加入活結點優先隊列
MinHeapNode mi;
mi.i = j;
mi.length = dist[j];
if(qq.full()){
break;
}
qq.queryIn(mi); //元素入隊
}
}//for迴圈結束
if(qq.empty()){
break;
}
qq.queryOut(); //當該結點的孩子結點全部入隊後,刪除該結點
}//while迴圈結束
}//方法結束
};//類結束
int main(){
Graph g;
g.shortestPath(1);
cout<<"最短路徑長為 "<<dist[n-1]<<endl;
cout<<"中間路徑為: ";
for(int i =3;i<n;i++){
cout<<prev[i]<<" ";
}
cout<<endl<<"歡迎使用本系統"<<endl;
return 0;
}