1. 程式人生 > >PAT 1030 Travel Plan

PAT 1030 Travel Plan

 

A traveler's map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting city and the destination. If such a shortest path is not unique, you are supposed to output the one with the minimum cost, which is guaranteed to be unique.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 4 positive integers N, M, S, and D, where N (≤500) is the number of cities (and hence the cities are numbered from 0 to N−1); M is the number of highways; S and D are the starting and the destination cities, respectively. Then M lines follow, each provides the information of a highway, in the format:

City1 City2 Distance Cost

where the numbers are all integers no more than 500, and are separated by a space.

Output Specification:

For each test case, print in one line the cities along the shortest path from the starting point to the destination, followed by the total distance and the total cost of the path. The numbers must be separated by a space and there must be no extra space at the end of output.

Sample Input:

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

Sample Output:

0 2 3 3 40

#include <cstdio>
#include <vector>

using namespace std;

const int MAX = 5001;
const int INF = 100000001;

struct Node
{
    //下一條鄰接邊 本條鄰接邊所指向的點 兩點路徑 兩點消費
    int next,to,len,consume;
}e[MAX];

//N - 城市數 M - 路線數 起始城市 目標城市
int N,M,StartCity,AimCity;
vector<int> pre[MAX];//儲存最優路徑
int vis[MAX] = {false};//標誌
int d[MAX];//儲存路徑長度

int head[MAX];
int cnt = 0;

int optvalue = INF;//最終最優路徑的花費
vector<int> path,tempath;//最終路徑 臨時路徑

//構建鄰接表
void add(int x,int y,int length,int con){
    e[cnt].next = head[x];
    e[cnt].to = y;
    e[cnt].len = length;
    e[cnt].consume = con;
    head[x] = cnt;

    cnt++;
}
//迪傑斯特拉找最短路徑
void Dijkstra(){

    fill(d,d + MAX,INF);//開始將路徑都填充滿 最大值
    d[StartCity] = 0;//開始節點距離自己為0

    for(int i = 0;i < N;i++){
        int u = -1,min = INF;
        for(int j = 0;j < N;j++){//尋找下一個最短的路徑
            if(vis[j] == false && d[j] < min){
                min = d[j];
                u = j;
            }
        }

        if(u == -1)return;//無法繼續尋找 結束
        vis[u] = true;//標誌已訪

        for(int j = head[u];j != -1;j = e[j].next){
            if(vis[e[j].to] == false && d[u] + e[j].len < d[e[j].to]){//尋找到一條更短的路徑時
                d[e[j].to] = d[u] + e[j].len;

                pre[e[j].to].clear();//清空原有最短路徑
                pre[e[j].to].push_back(u);
            }else if(vis[e[j].to] == false && d[u] + e[j].len == d[e[j].to]){//尋找到一天相同長短的路徑時
                d[e[j].to] = d[u] + e[j].len;

                pre[e[j].to].push_back(u);//增添一條最短路徑
            }
        }
    }
}
//深搜尋找花費更優路徑
void DFS(int v){//v 當前節點
    if(v == StartCity){
        tempath.push_back(v);
        int value = 0;//路徑的花費
        //計算這條路徑的花費
        //注意 i 開始為 1 (i > 0 時 i 與 i - 1 已經包含了到 0 的情況 而且 否則容易陣列出界)
        for(int i = 1;i < tempath.size();i++){
            for(int j = head[tempath[i]];j != -1;j = e[j].next){
                if(e[j].to == tempath[i - 1])value += e[j].consume;
            }
        }

        if(value < optvalue){
            //記錄目前的最優路徑
            optvalue = value;
            path = tempath;
        }
        tempath.pop_back();
        return;//結束這次遞迴
    }

    tempath.push_back(v);
    for(int i = 0;i < pre[v].size();i++){
        DFS(pre[v][i]);//深搜尋找
    }
    tempath.pop_back();//v節點搜尋完
}

int main(int argc, char const *argv[]) {
    scanf("%d%d%d%d",&N,&M,&StartCity,&AimCity);

    fill(head,head + MAX,-1);//將head填滿 -1

    for(int i = 0;i < M;i++){
        int x,y,length,con;
        scanf("%d%d%d%d",&x,&y,&length,&con);

        //構建鄰接表 無向圖
        add(x,y,length,con);
        add(y,x,length,con);
    }

    Dijkstra();
    DFS(AimCity);//深搜最優

    //輸出路徑經過的點
    for(int i = path.size() - 1;i >= 0;i--){
        printf("%d ",path[i]);
    }
    printf("%d %d",d[AimCity],optvalue);//輸出最短距離 和 最短距離的最小花費
    return 0;
}