Sicily: Campus(Floyd-Warshall算法)

本文介绍了一种使用Floyd算法解决中山大学不同校区间寻找最短路径的问题。通过详细解析算法步骤及代码实现,帮助读者理解如何利用图论算法解决实际问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description
At present, Zhongshan University has 4 campuses with a total area of 6.17 square kilometers sitting respectively on both sides of the Pearl River or facing the South China Sea. The Guangzhou South Campus covers an area of 1.17 square kilometers, the North Campus covers an area of 0.39 square kilometers, the Guangzhou East Campus has an area of 1.13 square kilometers and the Zhuhai Campus covers an area of 3.48 square kilometers. All campuses have exuberance of green trees, abundance of lawns and beautiful sceneries, and are ideal for molding the temperaments, studying and doing research.

Sometime, the professors and students have to go from one place to another place in one campus or between campuses. They want to find the shortest path between their source place S and target place T. Can you help them?

Input
The first line of the input is a positive integer C. C is the number of test cases followed. In each test case, the first line is a positive integer N=(0<N<=100) that represents the number of roads. After that, N lines follow. The i-th(1<=i<=N) line contains two strings Si, Ti and one integer Di (0<=Di<=100). It means that there is a road whose length is Di between Si and Ti. Finally, there are two strings S and T, you have to find the shortest path between S and T. S, T, Si(1<=i<=N) and Ti(1<=i<=N) are all given in the following format:str_Campus.str_Place. str_Campus represents the name of the campus, and str_Place represents the place in str_Campus. str_Campus is "North", "South", "East" or "Zhuhai". str_Place is a string which has less than one hundred lowercase characters from “a-z”. You can assume that there is at most one road directly between any two places.

Output
The output of the program should consist of C lines, one line for each test case. For each test case, the output is a single line containing one integer. If there is a path between S and T, output the length of the shortest path between them. Otherwise just output “-1” (without quotation mark). No redundant spaces are needed.

Sample Input
1
2
South.xiaolitang South.xiongdelong 2
South.xiongdelong Zhuhai.liyuan 100
South.xiongdelong South.xiaolitang

Sample Output
2

求图的最短路径主要有两种方法:Dijkstra算法和Floyd算法。对于本题,我采用的是Floyd算法。

对于地图本身,我是用一个data数组来存取图结点的名字,也就是地点的名字,在用一个Graph数组来存取边的权值。

由于此题没有直接输入结点的值,故我们需要从关系的输入中提取。

对于Graph的初始化,根据题目意思和Floyd算法的需要,我们将对角线上的值初始化为0,其他初始化为无穷大。这里的无穷大最好不要设置成0x7fffffff,因为算法中涉及到权重的相加,两个0x7fffffff相加会超出int范围,可能会出错,因此我把无穷大定义为0xfffffff(毕竟对于中大,应该不会出现这么大的权重)。

对于Floyd算法,我推荐:坐在马桶上看算法:只有五行的Floyd最短路算法
只要三重循环就可以实现这个算法,非常简便,这也是我此题选择这个算法的原因。

这道题有几个坑:
1.当查询的地点是不存在且不相同时,输出-1;
2.当查询的地点不存在且相同时,输出0;
3.当查询的地点存在且相同时,输出为0.

即是:
1.不存在且不相同,输出为-1;
2.相同输出为0.

下面是我的代码:

# include <iostream>
# include <string>
# include <queue>
# define MAX 202

using namespace std;

string data[MAX]; // 存取结点数据
int Graph[MAX][MAX]; // 存取图的各边权值
int N; // 结点的数目

void Initialize() {
    N = 0;
    for (int i = 0; i < MAX; i++) {
        data[i] = "";
        for (int j = 0; j < MAX; j++) {
            if (i == j) {
                Graph[i][j] = 0; // 自己到自己路途为0
            } else { // 其他情况初始为无穷大
                Graph[i][j] = 0xfffffff; // 不能初始化到0x7fffffff,因为涉及到权值相加,可能会超出int的范围
            }
        }
    }
}

int find_index(string str) {
    for (int i = 0; i < N; i++) {
        if (data[i] == str) {
            return i;
        }
    }
    return -1;
}

void Floyd() {
    for (int k = 0; k < N; k++) {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (Graph[i][j] > Graph[i][k] + Graph[k][j]) {
                    Graph[i][j] = Graph[i][k] + Graph[k][j];
                }
            }
        }
    }
}

int min_lenth(string str1, string str2) {
    Floyd();
    if (Graph[find_index(str1)][find_index(str2)] == 0xfffffff) {
        return -1;
    }
    return Graph[find_index(str1)][find_index(str2)];
}

int main(void) {
    int T;
    cin >> T;
    while(T--) {
        Initialize();
        int case_num;
        cin >> case_num;
        for (int i = 0; i < case_num; i++) {
            string str1, str2;
            int len;
            cin >> str1 >> str2 >> len;
            int str1_index, str2_index;
            str1_index = find_index(str1);
            str2_index = find_index(str2);
            if (str1_index == -1) {
                data[N++] = str1;
                str1_index = N-1;
            }
            if (str2_index == -1) {
                data[N++] = str2;
                str2_index = N-1;
            }
            Graph[str1_index][str2_index] = Graph[str2_index][str1_index] = len;
        }
        string str1, str2;
        cin >> str1 >> str2;
        if (find_index(str1) == -1 || find_index(str2) == -1) {
            if (str1 == str2) {
                cout << "0" << endl;
            } else {
                cout << "-1" << endl;
            }
        } else {
            cout << min_lenth(str1, str2) << endl;
        }
    }
    return 0;
}

以上内容皆为本人观点,欢迎大家提出批评和指导,我们一起探讨!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值