1. 程式人生 > >九度:題目1008:最短路徑問題

九度:題目1008:最短路徑問題

題目描述:
給你n個點,m條無向邊,每條邊都有長度d和花費p,給你起點s終點t,要求輸出起點到終點的最短距離及其花費,如果最短距離有多條路線,則輸出花費最少的。
輸入:
輸入n,m,點的編號是1~n,然後是m行,每行4個數 a,b,d,p,表示a和b之間有一條邊,且其長度為d,花費為p。最後一行是兩個數 s,t;起點s,終點t。n和m為0時輸入結束。
(1<n<=1000, 0<m<100000, s != t)
輸出:
輸出 一行有兩個數, 最短距離及其花費。
樣例輸入:
3 2
1 2 5 6
2 3 4 5
1 3
0 0
樣例輸出:
9 11
分析:

乍一看像是dijkstra演算法,但是還多了一個求最少花費的條件,所以不能找到目標點就返回,必須將所有能到目標點的情況都要遍歷到,所以用SPFA演算法

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <queue>
using namespace std;
 
#define MAX 1002
#define INT 0x7fffffff
 
int w[MAX];
int cost[MAX];
bool vis[MAX];
struct node{
    int w,cost;
}map[MAX][MAX];
int n,m,a,b,d,p,s,t;
 
void SPFA(){
    for(int i=1;i<=n;i++){w[i]=INT;cost[i]=INT;vis[i]=false;}
    queue<int> q;
    q.push(s);
    w[s]=0;
    cost[s]=0;
    vis[s]=true;
    while(!q.empty()){
        int cur=q.front();q.pop();
        vis[cur]=false;
        for(int i=1;i<=n;i++){
            if(map[cur][i].w!=INT&&w[i]>=w[cur]+map[cur][i].w){
                w[i]=w[cur]+map[cur][i].w;
                cost[i]=min(cost[i],cost[cur]+map[cur][i].cost);
                if(!vis[i]){
                    vis[i]=true;
                    q.push(i);
                }
            }
        }
    }
}
int main(){
    //freopen("C:\\in.txt","r",stdin);
    while(~scanf("%d%d",&n,&m)){
        if(!n&&!m)break;
        for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){map[i][j].w=INT;map[i][j].cost=INT;}
        for(int i=1;i<=m;i++){
            scanf("%d%d%d%d",&a,&b,&d,&p);
            map[a][b].w=map[b][a].w=d;
            map[a][b].cost=map[b][a].cost=p;
        }
        scanf("%d%d",&s,&t);
        SPFA();
        printf("%d %d\n",w[t],cost[t]);
    }
    return 0;
}
/**************************************************************
    Problem: 1008
    User: starcuan
    Language: C++
    Result: Accepted
    Time:10 ms
    Memory:9376 kb
****************************************************************/