int n; // 总点数
int h[N], w[N], e[N], ne[N], idx; // 邻接表存储所有边
int dist[N]; // 存储每个点到1号点的最短距离
bool st[N]; // 存储每个点是否在队列中
// 求1号点到n号点的最短路距离,如果从1号点无法走到n号点则返回-1
int spfa()
{
memset(dist, 0x3f, sizeof dist); // 初始化距离数组为无穷大
dist[1] = 0; // 1号点到自身的距离为0
queue<int> q; // 使用队列进行广度优先搜索
q.push(1); // 将起始点1放入队列
st[1] = true; // 标记1号点已经在队列中
while (q.size())
{
auto t = q.front(); // 取出队首的点t
q.pop();
st[t] = false; // 将点t标记为不在队列中
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i]; // 遍历点t的所有邻接点j
if (dist[j] > dist[t] + w[i]) // 通过点t可以缩短到达邻接点j的距离
{
dist[j] = dist[t] + w[i]; // 更新dist[j]的值
if (!st[j]) // 如果邻接点j不在队列中
{
q.push(j); // 将j放入队列
st[j] = true; // 标记j已经在队列中
}
}
}
}
if (dist[n] == 0x3f3f3f3f) return -1; // 判断终点n的最短距离是否为无穷大
return dist[n]; // 返回终点n的最短距离作为结果
}
首先,我们定义了几个变量来存储图的信息,包括总点数n,邻接表的数组h、w、e、ne和idx,以及存储每个点到1号点的最短距离dist和存储每个点是否在队列中st。
然后,在spfa函数中,我们首先对dist进行了初始化,将所有点到1号点的距离都设置为无穷大,然后将1号点到1号点的距离设为0。
接下来,我们使用队列来实现广度优先搜索。我们将起始点1放入队列,并标记1号点已经在队列中。然后开始循环处理队列中的点,直到队列为空。
在循环中,我们取出队首的点t,并将其标记为不在队列中。然后遍历该点的所有邻接点,如果通过当前点t可以缩短到达邻接点j的距离,我们就更新dist[j]的值,并检查邻接点j是否已经在队列中,如果不在则将其放入队列中,并标记为已经在队列中。
最后,我们判断终点n的最短距离是否为无穷大,如果是则说明无法从1号点走到n号点,返回-1;否则就返回终点n的最短距离作为结果。
这个算法的核心是使用队列来进行广度优先搜索,不断更新每个点到1号点的最短距离,直到找到终点或者确定无法到达终点。这样可以保证我们找到的最短路径是正确的。