单源最短路
文字描述
准备: 我们开一个数组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
*/