题意
一个图中有T个点,C条无向边(连接 2 个城镇的道路),再给出一个起点和一个终点,求起点到终点的最短距离(数据保证至少存在一条道路)
分析
一个点到另一个点的最短距离怎么求? 当然是先求这个点到所有点的最短距离,然后就解决了,此题可以使用朴素dijkstra或者堆优化版dijkstra或者spfa,这确实是一道非常裸的求最短路模板题
代码
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f, N = 2510, M = 12410;
/*n为点数,m为无向边边数,d[i]表示源点到i号点的距离,
w,e,ne,h这四个数组是链式前向星数组,idx为使用到的索引,
x1为起点,x2为终点*/
int n, m, d[N], w[M], e[M], ne[M], h[M], idx, x1, x2;
/*st[i]为true表示i号点在队列中,
st[i]为false表示i号点不在队列中
*/
bool st[N];
void add(int a, int b, int c) {
e[++idx] = b; //e数组存储的是新添加的边的终点
w[idx] = c; //w数组存储的是新添加的边的权值
ne[idx] = h[a];//ne数组存储的是新添加的边的起点的上一条边的编号,如果这个起点只有这么一条边,则h[a]为0
h[a] = idx; //h[a]表示最新添加的以a为起点的一条边的存储位置,随后cur往下一个位置移动
}
void spfa() {
memset(d, INF, sizeof d);//初始化源点到所有点的最短距离为无穷大级别
d[x1] = 0; //源点到自身的最短距离为0
queue<int> q; //声明队列
q.push(x1); //把起点入队
st[x1] = 1; //标记起点在队列中
while (q.size()) {
//取出队头,并标记队头不在队列中
auto t = q.front();
q.pop();
st[t] = 0;
//对以t点为起点的出边进行遍历,如果有更短的距离则更新原来的状态
for (int i = h[t]; i; i = ne[i]) {
int j = e[i];
if (d[j] > d[t] + w[i]) {
d[j] = d[t] + w[i];
if (!st[j]) {
st[j] = 1;
q.push(j);
}
}
}
}
printf("%d", d[x2]); //输出源点到终点的最短距离
}
int main() {
//输入点数和边数,还有起点和终点
scanf("%d%d%d%d", &n, &m, &x1, &x2);
//输入无向边的信息
int a, b, c;
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
add(b, a, c);
}
spfa();
}