洛谷 P1339:[USACO09OCT] Heat Wave G ← Bellman-Ford 算法

【题目来源】

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 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

【输出样例】
7

【数据范围】
对于 100% 的数据,1≤n≤2500,1≤m≤6200,1≤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 算法的边集数组存图时,读入一条无向边,需要同时存入这两条有向边,才能完整表达双向连通关系。

【算法代码】

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

const int N=3e3+5;
const int M=2e4+5;
const int inf=0x3f3f3f3f;
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 i=1; i<=n-1; i++) {
        bool flag=0;
        for(int j=1; j<=2*m; j++) {
            int u=e[j].u,v=e[j].v,w=e[j].w;
            if(dis[u]!=inf && dis[v]>dis[u]+w) {
                dis[v]=dis[u]+w;
                flag=1;
            }
        }
        if(!flag) break;
    }
}

int main() {
    cin>>n>>m>>s>>t;
    int cnt=0;
    for(int i=1; i<=m; i++) {
        int u,v,w;
        cin>>u>>v>>w;
        e[++cnt]= {u,v,w};
        e[++cnt]= {v,u,w};
    }
    bellman();
    cout<<dis[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

相关推荐
1-1=01 小时前
C# 数据结构和特殊类型
数据结构·c#·.net·.netcore
希和20271 小时前
C语言程序设计题|有序数组插入数字冒泡排序
c语言·数据结构·算法
布莱克60512 小时前
C++ 中 map 的 insert 与 emplace:key 已存在时会覆盖吗?
开发语言·数据结构·c++·算法·map
D e re k ZH15 小时前
C++ 系统学习手记:从语法细节到工程实践
开发语言·数据结构·c++·算法
zh_xuan20 小时前
LeeCode 496. 下一个更大元素I
数据结构·算法·栈·单调栈
白杨尚青1 天前
C++进阶篇(五):红黑树——四条规则、三种插入情况与旋转变色
开发语言·数据结构·c++·stl·红黑树·平衡二叉树
likexuec2 天前
数据结构(2)
数据结构
D e re k ZH2 天前
C++ 标准库算法全景指南
数据结构·c++·算法
冻柠檬飞冰走茶2 天前
字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)
c语言·开发语言·数据结构·算法·动态规划
十二3 天前
【洛谷题解】P1083 [NOIP 2012 提高组] 借教室(二分答案 + 差分)
数据结构·c++·算法·蓝桥杯