n个点,m条无向边,每条边都有长度d和花费p,起点s终点t,求起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
Spfa。注意有重边,且当两边相等时取花费少的那条。
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
const int inf = 1<<20 ;
const int MAX = 1000+5 ;
int map[MAX][MAX] , fee[MAX][MAX] ;
int n , m ;
int dis[MAX] , cost[MAX];
bool had[MAX] ;
queue <int> q ;
inline void init() {
memset(had,0,sizeof(had)) ;
memset(cost,0,sizeof(cost)) ;
for (int i=0 ; i<=n ; i++) {
dis[i] = inf ;
for (int j=i+1 ; j<=n ; j++) {
map[i][j] = map[j][i] = inf ;
fee[i][j] = fee[j][i] = inf ;
}
}
}
void spfa(int s) {
dis[s] = 0 ;
q.push(s) ;
while (!q.empty()) {
int t = q.front() ; q.pop() ;
had[t] = 0 ;
for (int i=1 ; i<=n ; i++) {
if (map[t][i]==inf) continue ;
if (dis[i]>dis[t]+map[t][i] ||
(dis[i]==dis[t]+map[i][t]
&& cost[i]>cost[t]+fee[t][i])) {
dis[i]=dis[t]+map[t][i] ;
cost[i]=cost[t]+fee[t][i];
if (!had[i]) {
had[i]=1;
q.push(i);
}
}
}
}
}
int main() {
//freopen("in.txt" , "r" , stdin) ;
while (cin >> n >> m) {
if (!n && !m) break ;
init() ;
while (m--) {
int a , b , d , p ;
scanf("%d%d%d%d" , &a , &b , &d , &p) ;
if (d<map[a][b]) {
map[a][b] = map[b][a] = d ;
fee[a][b] = fee[b][a] = p ;
}
else if(d==map[a][b] && p<fee[a][b]) {
fee[a][b] = fee[b][a] = p ;
}
}
int s , t ;
cin >> s >> t ;
spfa(s) ;
printf("%d %d\n" , dis[t] , cost[t]) ;
}
return 0;
}