【ACM】- PAT. A1030 Travel Plan 【图 - 最短路径】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_26398495/article/details/82053997
题目链接
题目分析:

结点编号 0 ~ N-1
题目满足最优子结构,可以直接得出最佳最短路径;也可以先保存所有最短路径,最后统一筛选!


思路一:

直接在遍历Dijkstra()过程中选出最佳最短路径

/**********************************
*@ID: 3stone
*@ACM: PAT.A1030 Travle Plan
*@Time: 18/8/21
*@IDE: VSCode 2018 + clang++
***********************************/
#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 505;
const int INF = 0x7fffffff;
int N, M, S, D;

int G[maxn][maxn];  //图
int d[maxn]; //最短距离
int cost[maxn][maxn];  //边的权重
int c[maxn]; //到每个点的最小花费
bool vis[maxn]; //标记是够访问
int pre[maxn]; //记录前驱结点

void Dijkstra(int s) {
    //初始化起点
    c[s] = 0; d[s] = 0; 

    for(int i = 0; i < N; i++) { //遍历n次,每次取一个点
        //选择最近点
        int u = -1, MIN = INF;
        for(int j = 0; j < N; j++) {
            if(vis[j] == false && d[j] < MIN) {
                u = j;
                MIN = d[j];
            }
        }
        if(u == -1) return;
        vis[u] = true;
        //更新最短距离 & 花费
        for(int v = 0; v < N; v++) {
            if(vis[v] == false && G[u][v] != INF) {
                if(d[u] + G[u][v] < d[v]){
                    d[v] = d[u] + G[u][v];
                    c[v] = c[u] + cost[u][v]; //更新花费
                    pre[v] = u;
                } else if(d[u] + G[u][v] == d[v] && c[u] + cost[u][v] < c[v]) {
                    c[v] = c[u] + cost[u][v];
                    pre[v] = u;
                }
            }
        }//for - v
    }//for - i

}//Dijkstra


void dfs_route(int ed) {
    if(ed == S){
        printf("%d ", S);
        return;
    }
    dfs_route(pre[ed]);
    printf("%d ", ed);
}

int main() {
    int c1, c2, route_dis, route_cost;
    while(scanf("%d%d%d%d", &N, &M, &S, &D) != EOF) {

        //初始化
        fill(G[0], G[0] + maxn * maxn, INF);
        fill(cost[0], cost[0] + maxn * maxn, INF);
        fill(vis, vis + maxn, false);
        fill(d, d + maxn, INF);

        //输入路径信息
        for(int i = 0; i < M; i++) {
            scanf("%d%d%d%d", &c1, &c2, &route_dis, &route_cost);
            G[c1][c2] = route_dis;
            G[c2][c1] = route_dis;
            cost[c1][c2] = route_cost;
            cost[c2][c1] = route_cost;
        }

        Dijkstra(S);

        dfs_route(D);
        printf("%d %d\n", d[D], c[D]);

    }//while

    return 0;
}
思路二:

保存所有最短路径,最后统一筛选!

/**********************************
*@ID: 3stone
*@ACM: PAT.A1030 Travle Plan
*@Time: 18/8/21
*@IDE: VSCode 2018 + clang++
***********************************/
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;

const int maxn = 505;
const int INF = 0x7fffffff;
int N, M, S, D;

int G[maxn][maxn];  //图
int d[maxn]; //最短距离
int cost[maxn][maxn];  //边的权重
bool vis[maxn]; //标记是够访问
vector<int> pre[maxn]; //记录前驱结点

void Dijkstra(int s) {
    //初始化起点
    d[s] = 0; 

    for(int i = 0; i < N; i++) { //遍历n次,每次取一个点
        //选择最近点
        int u = -1, MIN = INF;
        for(int j = 0; j < N; j++) {
            if(vis[j] == false && d[j] < MIN) {
                u = j;
                MIN = d[j];
            }
        }
        if(u == -1) return;
        vis[u] = true;
        //更新最短距离 & 花费
        for(int v = 0; v < N; v++) {
            if(vis[v] == false && G[u][v] != INF) {
                if(d[u] + G[u][v] < d[v]){
                    d[v] = d[u] + G[u][v];
                    pre[v].clear();
                    pre[v].push_back(u);
                } else if(d[u] + G[u][v] == d[v]) {
                    pre[v].push_back(u);
                }
            }
        }//for - v
    }//for - i

}//Dijkstra


vector<int> best_route; //最佳最短路径
int min_cost;  // 最小花费

void dfs_route(int ed, vector<int> cur_route, int cur_cost) {
    if(ed == S) {
        if(cur_cost < min_cost){
            best_route = cur_route;
            min_cost = cur_cost;
        }
    }
    for(int i = 0; i < pre[ed].size(); i++) {
        int pre_node = pre[ed][i];
        cur_route.push_back(pre_node);
        //也可以每步不累加价值,直到回溯至起点时,在枚举路径(不满足最优子结构的只能这样啦!)
        dfs_route(pre_node, cur_route, cur_cost + cost[ed][pre_node]);
        cur_route.pop_back();
    }
}

int main() {
    int c1, c2, route_dis, route_cost;
    while(scanf("%d%d%d%d", &N, &M, &S, &D) != EOF) {

        //初始化
        fill(G[0], G[0] + maxn * maxn, INF);
        fill(cost[0], cost[0] + maxn * maxn, INF);
        fill(vis, vis + maxn, false);
        fill(d, d + maxn, INF);

        //输入路径信息
        for(int i = 0; i < M; i++) {
            scanf("%d%d%d%d", &c1, &c2, &route_dis, &route_cost);
            G[c1][c2] = route_dis;
            G[c2][c1] = route_dis;
            cost[c1][c2] = route_cost;
            cost[c2][c1] = route_cost;
        }

        Dijkstra(S);

        vector<int> cur_route;
        cur_route.push_back(D);
        min_cost = INF;
        dfs_route(D, cur_route, 0);

        for(int i = best_route.size() - 1; i >= 0; i--) {
            printf("%d ", best_route[i]);
        }
        printf("%d %d\n", d[D], min_cost);

    }//while

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_26398495/article/details/82053997
今日推荐