
【题目来源】https://www.luogu.com.cn/problem/P1339【题目描述】有一个 n 个点 m 条边的无向图请求出从 s 到 t 的最短路长度。【输入格式】第一行四个正整数 n,m,s,t。 接下来 m 行每行三个正整数 u,v,w表示一条连接 u,v长为 w 的边。【输出格式】输出一行一个整数表示答案。【输入样例】7 11 5 42 4 21 4 37 2 23 4 35 7 57 3 36 1 16 3 42 4 35 6 37 2 1【输出样例】7【数据范围】对于 100% 的数据1≤n≤25001≤m≤62001≤w≤1000。【算法分析】● Bellman-Ford 算法使用边集数组存图而非邻接表。这是因为 Bellman-Ford 在每一轮迭代中都需要遍历图中全部边执行松弛操作无需查询某个顶点的出边。而邻接表的核心优势是快速获取单个顶点的邻接边但这项能力在 Bellman-Ford 算法中完全用不到。因此邻接表额外的索引结构自然成为冗余。反观边集数组它仅存储每条边自身的信息结构极简恰好适配 Bellman-Ford 算法的执行逻辑。● 包含 n 个顶点的图其最短路径一定是简单路径路径中不会重复经过同一个顶点不含任何环即最多包含 n-1 条边。所以Bellman-Ford 算法最多只需要松弛 n-1 轮。1算法的第 k 轮松弛作用是求出“最多经过 k 条边”能够得到的最短距离。第 1 轮更新仅用 1 条边可达的最短路第 2 轮更新最多 2 条边的最短路以此类推。当完成 n-1 轮松弛后所有简单路径对应的最短距离都已经被更新完成。2如果执行完 n-1 轮之后仍然还有边可以继续松弛就说明图中存在“负环”。即可以不断环绕这个环无限降低路径总权值不存在有限的最短路径。● 本题为无向图。无向边 u-v 等价于两条方向相反的有向边u → v 与 v → u。因此在使用 Bellman‑Ford 算法的边集数组存图时读入一条无向边需要同时存入这两条有向边才能完整表达双向连通关系。【算法代码】#include bits/stdc.h using namespace std; const int N3e35; const int M2e45; const int inf0x3f3f3f3f; int dis[N]; struct edge { int u,v,w; } e[M]; int n,m,s,t; void bellman() { memset(dis,inf,sizeof dis); dis[s]0; for(int i1; in-1; i) { bool flag0; for(int j1; j2*m; j) { int ue[j].u,ve[j].v,we[j].w; if(dis[u]!inf dis[v]dis[u]w) { dis[v]dis[u]w; flag1; } } if(!flag) break; } } int main() { cinnmst; int cnt0; for(int i1; im; i) { int u,v,w; cinuvw; e[cnt] {u,v,w}; e[cnt] {v,u,w}; } bellman(); coutdis[t]; return 0; } /* in: 7 11 5 4 2 4 2 1 4 3 7 2 2 3 4 3 5 7 5 7 3 3 6 1 1 6 3 4 2 4 3 5 6 3 7 2 1 out: 7 */【参考文献】https://www.luogu.com.cn/problem/solution/P1339