(dijkstra演算法+多權值)最短路徑問題
阿新 • • 發佈:2019-01-22
給你n個點,m條無向邊,每條邊都有長度d和花費p,給你起點s終點t,要求輸出起點到終點的最短距離及其花費,如果最短距離有多條路線,則輸出花費最少的。
Input
輸入n,m,點的編號是1~n,然後是m行,每行4個數 a,b,d,p,表示a和b之間有一條邊,且其長度為d,花費為p。最後一行是兩個數 s,t;起點s,終點。n和m為0時輸入結束。
(1< n< =1000, 0< m< 100000, s != t)
Output
輸出 一行有兩個數, 最短距離及其花費。
Sample Input
3 2
1 2 5 6
2 3 4 5
1 3
0 0
Sample Output
9 11
分析與解答
這題我除錯了八個小時
我總結一下我對dijkstra的認識
1.dijkstra演算法可以求從單個源點出發到所有結點的最短路,這個題就是坑到這了,我寫兩個引數就wrong answer了,就是說,你呼叫這個函式只需要一個引數,就是起點。終點是n已經固定了,現在你說終點是t,哪怕走到終點n的路不經過t,你輸出dis[t],也是從起點到t的最短路。
每標記一次就說明被標記的這個數的dis已經確定了。我們迴圈n次目的就是為了標記n次確定n個數的dis。我們初始化起點的dis是0其他的是inf,我們迴圈n次,第一個確定下來的就是起點。然後標記,注意這個標記是在那n次迴圈裡的。
2.這個題第二個坑就是,兩個點之間的路有多條,如果路的距離相同時,還要找花費最小的
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 100100
using namespace std;
int vis[1100];int dis[1100];
int map[1100][1100];
int value[1100][1100];
int v[1100];
int n;
void dijkstra(int s){
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;++i){
dis[i]=INF;
v[i]=INF;
}
dis[s]=v[s]=0 ;
for(int i=1;i<=n;++i){//迴圈n次,每一次都選一個點標記上
int x,m=INF;
for(int y=1;y<=n;++y){//所有未標號節點中選dis最小的結點
if(!vis[y]&&dis[y]<=m)
m=dis[x=y];
}
vis[x]=1;
for(int y=1;y<=n;++y)//從x出發的所有邊(x,y),更新dis[y]
{
if (dis[y] > dis[x] + map[x][y]){
dis[y]= dis[x]+map[x][y];
v[y] = v[x] + value[x][y];
}
else if (dis[y] == dis[x] + map[x][y] && v[y] > v[x] + value[x][y]){
v[y] = v[x] + value[x][y];
}
}
}
}
int main() {
int m;
int a,b,c,p;
int s,t;
while(cin>>n>>m){
if(m==0&&n==0) return 0;
//
// memset(v,INF,sizeof(v));
memset(map,INF,sizeof(map));
memset(value,INF,sizeof(value));
for(int i=0;i<m;++i){
scanf("%d%d%d%d",&a,&b,&c,&p);
if(c<map[a][b]){
map[a][b]=map[b][a]=c;
value[a][b]=value[b][a]=p;
}
if(c==map[a][b]&&value[a][b]>p){
value[b][a]=value[a][b]=p;
}
}
scanf("%d%d",&s,&t);
dijkstra(s);
printf("%d %d\n",dis[t],v[t]);
}
}