【ACM】- PAT. A1087All Roads Lead to Rome 【图 - 最短路径】

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

给出无向图,边和结点都有权重,查找最短路径;
当最短路径有多条时,选择结点权重总和最大的那条,若还有多条,选择平均结点权重最大的一条路径;

解题思路

使用Dijkstra()算法 查找最短路径;
本题满足最优子结构,故对于多条最短路径,可以在查找过程中就判断那条最佳(判断稍复杂),
也可以保存所有路径,最后筛选!

注意点:
结点是以三位大写字母组成的名字给出的,
可以使用map<string, int>map<int, string> 形成映射关系;也可用Hash字符串;


AC程序(C++)
/**********************************
*@ID: 3stone
*@ACM: PAT.A1087 All Roads Lead to Rome
*@Time: 18/8/22
*@IDE: VSCode 2018 + clang++
***********************************/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<iostream>
using namespace std;

const int INF = 0x7fffffff;
const int maxn = 210;

int G[maxn][maxn]; //图
vector<int> pre[maxn]; // 前驱结点
int d[maxn]; //保存最小花费
bool vis[maxn]; //标记是否访问
int happiness[maxn];  //结点权重
int route_num[maxn]; //最短路径条数

int N, K;//结点数,边数
map<string, int> name_to_key;
map<int, string> key_to_name;

void Dijkstra(int s) {
    d[s] = 0;
    route_num[s] = 1;
    for(int i = 1; i <= N; i++) {

        int u = -1, MIN = INF;
        for(int j = 1; 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 = 1; 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);
                    route_num[v] = route_num[u];
                } else if(d[u] + G[u][v] == d[v]) {
                    pre[v].push_back(u);
                    route_num[v] += route_num[u];
                }

            }//if
        }//for - v

    }//for - i

}//Dijkstra

vector<int> best_route;
int Max_Sum_Happ, Max_Avg_Happ;

//DFS筛选最佳最短路径
void dfs_route(int ed, vector<int> cur_route, int sum_happ, int sum_cty) {

    if(ed == 1) { //回溯至起点
        if(sum_happ > Max_Sum_Happ) {
            Max_Sum_Happ = sum_happ;
            Max_Avg_Happ = sum_happ / sum_cty;
            best_route = cur_route;
        } else if(sum_happ == Max_Sum_Happ && Max_Avg_Happ < (sum_happ / sum_cty) ) {
            Max_Avg_Happ = sum_happ / sum_cty;
            best_route = cur_route;
        }

    }

    for(int i = 0; i < pre[ed].size(); i++) {
        int v = pre[ed][i];
        cur_route.push_back(v);
        dfs_route(v, cur_route, sum_happ + happiness[v], sum_cty + 1);
        cur_route.pop_back();
    }   
}


//初始化
void initialize() {
    name_to_key.clear();
    key_to_name.clear();
    fill(d, d + maxn, INF);
    fill(vis, vis + maxn, false);
    fill(G[0], G[0] + maxn * maxn, INF);
    fill(route_num, route_num + maxn, 0);
    Max_Avg_Happ = -1;
    Max_Sum_Happ = -1;
}

int main(){
    char st[4]; //起点城市
    char c1[4], c2[4]; //路径两端的城市名
    int ed, cost; //重点编号,路径花费
    while(scanf("%d %d %s", &N, &K, st) != EOF) {

        //初始化
        initialize();

        int key = 1;
        name_to_key[st] = key; //起点映射
        key_to_name[key++] = st;
        //输入N-1个城市的幸福度
        for(int i = 1; i < N; i++) { 
            scanf("%s", c1);
            if(strcmp(c1, "ROM") == 0) ed = key; //记录终点编号
            name_to_key[c1] = key;
            key_to_name[key] = c1;
            cin >> happiness[key++];
        }
        //输入K条路径信息
        for(int i = 0; i < K; i++) {
            scanf("%s %s %d", c1, c2, &cost);
            G[name_to_key[c1]][name_to_key[c2]] = cost;
            G[name_to_key[c2]][name_to_key[c1]] = cost;
        }

        Dijkstra(1);

        vector<int> cur_vector;
        cur_vector.push_back(ed);
        dfs_route(ed, cur_vector, happiness[ed], 0);

        printf("%d %d %d %d\n", route_num[ed], d[ed], Max_Sum_Happ, Max_Avg_Happ);
        for(int i = best_route.size() - 1; i > 0; i--) {
            printf("%s->", key_to_name[best_route[i]].c_str());
        }
        printf("%s\n", key_to_name[best_route[0]].c_str());

    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_26398495/article/details/82081262