1. Realizar con matriz de adyacencia (para ser llenado...)
2. Realizar con lista de adyacencia
definición de lista de adyacencia
#define MaxVertexnum 100 //最大顶点数量
int dis[MaxVertexnum] = { 0 }; //单源最短路径
bool vis[MaxVertexnum] = { 0 }; //访问标志位
#define INF 0x7fffffff //最大值
#define VertexType int //顶点类型
#define InfoType int //边权重类型
typedef struct ArcNode{
int adjvex; //边指向结点
InfoType info; //边权重
struct ArcNode* next;
};
typedef struct VNode {
VertexType name;
ArcNode* first;
}AdjList[MaxVertexnum];
typedef struct {
AdjList node;
int vexnum;
int arcnum;
}ALGraph;
Comprensión concreta, un total de tres estructuras están conectadas entre sí, lo que se puede comparar con la representación del hermano menor y la clasificación radix del árbol y el método de la cremallera de la tabla hash. Los tres tienen el mismo efecto.
dijkstra logra
- Primero encuentre el punto no visitado u con la distancia más pequeña en la lista actual de dis [] distancia
- Si no se encuentra, significa que se ha calculado la distancia más corta de todos los puntos
- Si lo encuentra, elimine todos los puntos adyacentes de u, calcule y actualice la distancia más corta
- Vuelva al paso (1) y continúe hasta completar la operación
void dijkstra(ALGraph* G, int start) {
fill(vis, vis + MaxVertexnum, 0); //访问标志初始化
fill(dis, dis + MaxVertexnum, INF); //路径初始化
dis[start] = 0; //源点到自己的距离为0
int i, j, u, min;
for (i = 0; i < G->vexnum; i++) {
u = -1; //在未被访问过的顶点中找到距离最短的点
min = INF;
for (j = 1; j <= G->vexnum; j++) {
if (vis[j] = false && dis[j] < min) {
u = j;
min = dis[j];
}
}
if (u == -1) return; //所有顶点均已访问
vis[u] = true;
ArcNode* tmp = G->node[u].first; //找到距离最短的顶点u的邻接点
printf("\n\n\n");
while (tmp) {
//若该邻接点未被访问过 且 源点到u的最短距离+u到该邻接点的距离小于该邻接点此前的最短距离
if (vis[tmp->adjvex] == false && dis[u] + tmp->info < dis[tmp->adjvex])
dis[tmp->adjvex] = dis[u] + tmp->info;
tmp = tmp->next; //继续访问u的下一个邻接点
}
}
}
3. Implementación abstracta de la plantilla del algoritmo de Dijkstra (para preguntas)
#include <bits/stdc++.h>
using namespace std;
struct node {
int id, dis;
bool friend operator < (const node& a, const node& b) {
return a.dis > b.dis;
}
};
int n, m, s;
int ui, vi, wi;
vector<pair<int, int>> E[100];
int dis[100];
int vis[100];
void dijkstra() {
fill(dis, dis + 100, 1e9); //初始化dis列表
dis[s] = 0;
priority_queue<node> Q;
Q.push(node{ s, 0 });
while (!Q.empty()) {
int Now = Q.top().id; //当前Now顶点的距离最短
int D = Q.top().dis; //D为Now顶点目前的最短距离
Q.pop();
//对应底下①语句,因每次更新数据都会把距离放进列表,故当计算完所有距离后依旧留下一堆无用数据,用此语句进行过滤
if (vis[Now]) continue;
vis[Now] = 1;
for (auto it : E[Now]) { //访问Now的所有邻边
int des = it.first;
int weigh = it.second;
if (dis[des] > D + weigh) { //源点到Now的距离+Now到des的距离 < 先前des的最短距离
dis[des] = D + weigh;
Q.push(node{ des, dis[des] }); //①
}
}
}
}
int main() {
cin >> n >> m >> s; //n:顶点数 m:边数,s:源点
for (int i = 0; i < m; i++) {
cin >> ui >> vi >> wi; //从ui到vi权重为wi的一条边
E[ui].push_back({ vi,wi });
}
dijkstra();
for (int i = 1; i <= n; i++) {
printf("%d ", dis[i]);
}
return 0;
}
La plantilla se puede entender concretamente por la siguiente figura
Si desea obtener esta imagen, debe ingresar los datos de esta manera y comparar los datos de entrada con la estructura abstracta a la derecha de la imagen de arriba, y puede encontrar la conexión interna
5 8 0
0 1 1
0 2 2
0 4 1
2 1 3
2 3 2
2 4 2
3 4 1
3 1 2
Muestras de entrada y salida
entrada #1
4 6 1 1 2 2 2 3 2 2 4 1 1 3 5 3 4 3 1 4 4
Salida #1
0 2 4 3
4. Algoritmo de Floyd
Añadir un algoritmo de Floyd como complemento
int n;
int A[100][100], path[100][100];
void floyd() {
fill(path, path + 10000, -1); //初始化path数组为-1
for (int k = 0; k < n; k++) { //考虑以Vk作为中转点
for (int i = 0; i < n; i++) { //遍历整个矩阵,i为行号,j为列号
for (int j = 0; j < n; j++) {
if (A[i][j] > A[i][k] + A[k][j]) { //以Vk为中转点的路径更短
A[i][j] = A[i][k] + A[k][j]; //更新最短路径长度
path[i][j] = k; //中转点
}
}
}
}
}