单源最短路

单源最短路

文字描述

准备: 我们开一个数组dis(int类型)记录各结点与源点的距离和一个数组vis(bool类型)记录各个结点的访问情况

初始化: 我们将dis数组全赋值为inf(不可能达到的最长距离, 0x3f3f3f3f或者0x3f3f3f3f3f3f3f3f),然后将dis1赋值为0,然后将vis全部赋值为false

操作: 每次遍历所有结点,找到未访问结点中与源点距离最小的(也就是vis任然为false且dis最小的)并将这个结点对应的vis更新为true,然后我们遍历从这个结点出发的所有边并更新dis(如果我们找到的结点是x且存在一条从x到y距离为s的路径,则我们进行操作dis[y] = min(dis[y], dis[x]+s) )。

重复操作直到所有结点的vis都为true为止

代码实现

#include<map>
#include<queue>
#include<string>
#include<iomanip>
#include<iostream>
#include<algorithm>
using namespace std;

struct road{
    int to, distance;

    road(){}
    road(int to, int distance): to(to), distance(distance){}
};

const int maxn = 25;
const int inf = 0x3f3f3f3f;
int dis[maxn], precursor[maxn];
bool vis[maxn];
map<char, int> node_to_num;
char num_to_node[maxn];
queue<road> node[maxn];

void data_in(int &node_num) {
    string str_node;
    int road_num, start_node, end_node, distance;
    cin >> node_num >> road_num >> str_node;

    // 记录数字对应字母结点和字母结点对应的数字
    for(int i = 0; i < node_num; i++) num_to_node[i+1] = str_node[i], node_to_num[str_node[i]] = i+1;

    // 申请临时储存线路的矩阵并全赋值为0
    int **dis_matrix = new int*[node_num+1];
    for(int i = 0; i <= node_num; i++) dis_matrix[i] = new int[node_num+1]();

    for(; road_num; road_num--) {
        cin >> str_node >> distance;
        start_node = node_to_num[str_node[0]];
        end_node = node_to_num[str_node[1]];
        node[start_node].push(road(end_node, distance));
        dis_matrix[start_node][end_node] = distance;
    }

    // 输出初始线路
    cout << endl << "====================================================" << endl;
    cout << "对应矩阵为:" << endl << setw(5) << "";
    for(int i = 1; i <= node_num; i++) cout << setw(5) << num_to_node[i];
    for(int i = 1; i <= node_num; i++) {
        cout << endl << setw(5) << num_to_node[i];
        for(int j = 1; j <= node_num; j++) (i == j || dis_matrix[i][j]) ? cout << setw(5) << dis_matrix[i][j]: cout << setw(5) << "inf";
    }

    // 释放
    for(int i = 0; i <= node_num; i++) {
        delete[] dis_matrix[i];
        dis_matrix[i] = nullptr;
    }
    delete[] dis_matrix;
    dis_matrix = nullptr;
}

void init(const int source, const int node_num) {
    for(int i = 0; i <= node_num; i++) dis[i] = inf, vis[i] = false, precursor[i] = source;
    dis[source] = 0; precursor[source] = 0;
}

void calculate(const int node_num) {
    while(true) {
        int min_dis = 0;
        for(int i = 1; i <= node_num; i++) if(!vis[i] && dis[i] < dis[min_dis]) min_dis = i;
        if(!min_dis) return;
        vis[min_dis] = true;
        while(!node[min_dis].empty()) {
            road tmp = node[min_dis].front(); node[min_dis].pop();
            if(dis[tmp.to] > dis[min_dis]+tmp.distance) {
                // 最短路更新时不要忘记更新前驱
                dis[tmp.to] = dis[min_dis]+tmp.distance;
                precursor[tmp.to] = min_dis;
            }
        }
    }
}

void path_out(int node_i) {
    if(precursor[node_i]) {
        path_out(precursor[node_i]);
        cout << setw(5) << "-->" << setw(3) << num_to_node[node_i];
    } else cout << setw(3) << num_to_node[node_i];
}

void data_out(const int node_num) {
    cout << endl << "====================================================" << endl;
    cout << "最短路径为:" << endl;
    for(int i = 2; i <= node_num; i++) {
        path_out(i);
        dis[i] == inf? cout << "无路径" << endl: cout << "长度" << dis[i] << endl;
    }
}

int main() {
    int source = 1, node_num;
    cout << left;
    data_in(node_num);
    init(source, node_num);
    calculate(node_num);
    data_out(node_num);
    return 0;
}

/*
6 8
ABCDEF
AC 10
AE 30
AF 100
BC 5
CD 50
DF 10
ED 20
EF 60
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值