1. 程式人生 > >step6 演算法 HDU3790 最短路徑問題【Dijkstra演算法】

step6 演算法 HDU3790 最短路徑問題【Dijkstra演算法】

思路:迪傑斯特拉演算法

#include<iostream>
#include<vector> 
#include<queue> 
#define inf 0x3f3f3f3f
#define maxn 1005
using namespace std;
class Edge{
	public:
		int v,cost,pay;//cost代表長度、 pay代表花費
		Edge(){
		}
		Edge(int vv,int cc,int pp){
			v=vv;
			cost=cc;
			pay=pp;
		} 
};
class Node{
	public:
		int v;
		int cost;
		Node (int vv=0,int c=0){
			v=vv;
			cost=c;
		}
		//優先順序佇列將使用下面的過載
		friend bool operator<(Node n1,Node n2){
			return n1.cost>n2.cost;
		} 

}; 


vector<Edge>g[maxn];   //無向圖 
bool marked[maxn];	   //D演算法中每個頂點僅處理一遍
int disto[maxn];		//出發點到某點距離
int costo[maxn];		//接通改點需要增加的邊的花費 
int n,m;

void dijkstra(int s,int u){
	//初始化 
	for(int i=0;i<=n;i++) {
		marked[i]=false;
		disto[i]=inf;
		costo[i]=inf;
	}
	costo[s]=disto[s]=0;
	priority_queue<Node>pq;//儲存<v,disto[v]>且按disto[v]升序排列 
	pq.push(Node(s,0));
	
	Node tmp;
	while(!pq.empty()){
		tmp=pq.top();
		pq.pop();
		int v=tmp.v;
		if(marked[v])continue;
		if(v==u)return;
		marked[v]=true;
		int len=g[v].size();
		for(int i=0;i<len;i++){
			int vv=g[v][i].v;
			if(marked[vv])continue;
			int cost=g[v][i].cost;
			int pay=g[v][i].pay;
			
			//判斷已經算得的到另一個點的距離是否需要迭代,
			//即同現有點加上現有點到另一個點的消耗 比較 
			if(disto[vv]>disto[v]+cost){
				disto[vv]=disto[v]+cost;
				costo[vv]=costo[v]+pay;			//增加的內容
				pq.push(Node(vv,disto[vv])) ;
			}
			
			//增加的內容
			//加入點vv時若出現多種距離相同的方案,選取新邊最小的那個
			if(disto[vv]==disto[v]+cost){
				costo[vv]=min(costo[vv],costo[v]+pay);
			}
		}
	}
}
	
	


int main(){
	std::ios::sync_with_stdio(false);
    std::cin.tie(0); 
	while(cin>>n>>m&&n!=0){	
		for(int i=0;i<=n;i++)g[i].clear();
		for(int i=0;i<m;i++){
			int a,b,c,d;		
			cin>>a>>b>>c>>d;
			Edge edge;
			edge.v=b;
			edge.cost=c;
			edge.pay=d;
			g[a].push_back(edge);
			edge.v=a;
			g[b].push_back(edge);
		}
		int a,b;cin>>a>>b;
		dijkstra(a,b);
		cout<<disto[b]<<" "<<costo[b]<<endl;
	}
	
	return 0;
}