如果是无向图,只需要变更 G[a][b] = min(G[a][b], c);
变为G[a][b] = G[b][a] = min(G[a][b],c);
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1005; // 定义最大节点数
const int INF = 1e9; // 定义无穷大,用于表示两个节点之间没有边
int G[MAXN][MAXN]; // 定义图的邻接矩阵表示,G[i][j]表示节点i到节点j的边的权值
int dist[MAXN]; // 定义数组dist,dist[i]用于存储源节点到节点i的最短距离
bool visited[MAXN]; // 定义数组visited,visited[i]用于标记节点i是否已经被访问
// Dijkstra算法函数,参数s表示源节点,n表示节点总数
void Dijkstra(int s, int n)
{
// 初始化最短距离为无穷大
for (int i = 1; i <= n; i++)
{
dist[i] = INF;
}
// 源节点到自己的最短距离为0
dist[s] = 0;
// 主循环,每次找到一个最短路径节点
for (int i = 1; i <= n; i++)
{
int u = -1, MIN = INF;
// 下面的for循环是在未访问的节点中找到最短路径最小的节点
//(1)它的目的是在所有未被访问过的节点中,找到一个从源节点出发的最短路径长度最小的节点。
//(2)具体来说,我们维护一个dist数组,其中dist[i]表示从源节点到节点i的最短路径长度。在每一轮循环中,我们遍历所有未被访问过的节点,找到dist值最小的节点,然后将这个节点标记为已访问。
//(3)这个步骤的目的是确保我们总是先处理离源节点最近的节点,这样我们就可以保证,当我们访问一个节点时,我们已经找到了从源节点到这个节点的最短路径。这是Dijkstra算法的贪心策略:总是先处理最“近”的节点。
for (int j = 1; j <= n; j++)
{
if (!visited[j] && dist[j] < MIN)
{
u = j;
MIN = dist[j];
}
}
// 如果找不到这样的节点,说明剩下的节点都不可达,直接返回
if (u == -1)
return;
// 标记节点u为已访问
visited[u] = true;
// 更新通过节点u可以缩短的路径
//(1)如果v已经被访问过,那么我们就跳过它,因为我们已经找到了从源节点到v的最短路径。
//(2)如果节点u到节点v之间没有边(即G[u][v]等于无穷大),那么我们也跳过它,因为我们不能通过u到达v。
//(3)如果从源节点到节点u的最短路径长度(dist[u])加上从节点u到节点v的边的权值(G[u][v])小于当前从源节点到节点v的最短路径长度(dist[v]),那么我们就找到了一条更短的路径,于是更新dist[v]。
for (int v = 1; v <= n; v++)
{
if (!visited[v] && G[u][v] != INF && dist[u] + G[u][v] < dist[v])
{
dist[v] = dist[u] + G[u][v];
}
}
}
}
int main()
{
int n, m;
cin >> n >> m;
// 初始化图的邻接矩阵为无穷大,表示所有节点之间都不可达
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
G[i][j] = INF;
}
}
// 读入边的信息,并更新邻接矩阵
for (int i = 0; i < m; i++)
{
int a, b, c;
cin >> a >> b >> c;
G[a][b] = min(G[a][b], c); // 有向图,只添加一条从a到b的边
}
// 调用Dijkstra算法计算最短路径
Dijkstra(1, n);
// 输出从1号点到n号点的最短路径长度
cout << dist[n] << endl;
return 0;
}