HDU-3790 最短路徑問題 (Dijkstra演算法優化)
阿新 • • 發佈:2018-11-01
題目:給你n個點,m條無向邊,每條邊都有長度d和花費p,給你起點s終點t,要求輸出起點到終點的最短距離及其花費,如果最短距離有多條路線,則輸出花費最少的。
這是一道模板題,然而卻做了整整一下午,剛開始用的Bellman-Ford的佇列優化做的,結果TLE,崩潰:(然後改成了優先佇列的,交上去以後MLE,崩潰+1:(今天真的是著實體會了一把從時間超限到記憶體超限的心痛,內心不甘,去網上搜了題解,發現原來這是一道Dijkstra演算法優化的模板題,原諒我的無知,因為在這之前我竟然不知道Dijkstra演算法優化,搞了一下午,最終還是搞出來了,心累~~~
首先要定義兩個結構體node和edge,便於動態陣列vector和優先佇列priority_queue資料型別的儲存,node結構體要過載運算子<,以便於確認優先佇列的優先順序,然後定義一個數組dis儲存路線的長度和花費,接下來就是Dijkstra模板,這道題不僅要輸出最短路徑,還要輸出花費,所以在最短路相同時比較一下花費就好了。
AC程式碼:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <queue> #include <stack> #include <vector> #include <map> #include <set> using namespace std; #define inf 0x3f3f3f const int MAX=1e3+5; struct node { int to; int length; int cost; node(int _to=0,int _length=0,int _cost=0):to(_to),length(_length),cost(_cost){} bool operator <(const node &x)const { if(length==x.length) return cost>x.cost; else return length>x.length; } }; struct edge { int to; int length; int cost; edge(int _to=0,int _length=0,int _cost=0):to(_to),length(_length),cost(_cost){} }; struct dist { int way; int money; }dis[MAX]; int n,m; int main() { while(scanf("%d%d",&n,&m)&&n&&m) { vector <edge> e[MAX]; for(int i=1;i<=m;i++) { int a,b,c,d; scanf("%d%d%d%d",&a,&b,&c,&d); e[a].push_back(edge(b,c,d)); e[b].push_back(edge(a,c,d)); } int st,en; scanf("%d%d",&st,&en); for(int i=1;i<=n;i++) { dis[i].way=inf; dis[i].money=inf; } priority_queue <node> q; while(!q.empty()) q.pop(); dis[st].money=0; dis[st].way=0; q.push(node(st,0,0)); node tmp; while(!q.empty()) { tmp=q.top(); q.pop(); int u=tmp.to; for(int i=0;i<e[u].size();i++) { int to=e[u][i].to; int length=e[u][i].length; int cost=e[u][i].cost; if(dis[to].way>dis[u].way+length) { dis[to].way=dis[u].way+length; dis[to].money=dis[u].money+cost; q.push(node(to,dis[to].way,dis[to].money)); } else if(dis[to].way==dis[u].way+length&&dis[to].money>dis[u].money+cost) { dis[to].money=dis[u].money+cost; q.push(node(to,dis[to].way,dis[to].money)); } } } printf("%d %d\n",dis[en].way,dis[en].money); } return 0; }