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

相关推荐
quaer3 小时前
弗洛伊德算法--判圈法寻找环的入口O(n) O(1)
数据结构·算法
xys_6787 小时前
深挖数据结构:树和二叉树(上)
数据结构·算法
BeiGuTing_code7 小时前
Java动态数组(一)
java·数据结构·windows
Code_Solitude11 小时前
传智杯备赛代码整理(前4题)
数据结构·算法
Jasmine_llq12 小时前
《P8816 [CSP-J 2022] 上升点列》
数据结构·算法·贪心·排序·二维动态规划 dp·类背包状态转移
辛苦才能12 小时前
C++ 哈希表深度解析:删除为什么必须打标记,负载因子为什么卡 0.7
开发语言·数据结构·c++·算法
JasmineX-112 小时前
数据结构(笔记)——顺序栈
c语言·数据结构·笔记
凉茶钱14 小时前
list:哨兵节点,const_iterator 和 const iterator的区别与迭代器失效
数据结构·c++·list
敲代码的苦1315 小时前
头歌数据结构-排序的实现及其应用
数据结构
有同事要进步16 小时前
Leecode第68题:x的平方根
java·数据结构·算法