牛客题解 | 【模板】单源最短路1
1.牛客题解 | N皇后问题2.牛客题解 | [CQOI2007]涂色PAINT3.牛客题解 | [NOIP2001]装箱问题4.牛客题解 | [NOIP2002 普及组] 过河卒5.牛客题解 | [ZJOI2010]COUNT 数字计数6.牛客题解 | abb7.牛客题解 | ranko的手表8.牛客题解 | 【模板】01背包9.牛客题解 | 【模板】二维前缀和10.牛客题解 | 【模板】二维差分11.牛客题解 | 【模板】前缀和
12.牛客题解 | 【模板】单源最短路1
13.牛客题解 | 【模板】哈夫曼编码14.牛客题解 | 【模板】完全背包15.牛客题解 | 【模板】差分16.牛客题解 | 【模板】循环队列17.牛客题解 | 【模板】链表18.牛客题解 | 三角形最小路径和19.牛客题解 | 不相邻取数20.牛客题解 | 串21.牛客题解 | 乘积为正数的最长连续子数组22.牛客题解 | 买卖股票的最好时机(一)23.牛客题解 | 买卖股票的最好时机(三)24.牛客题解 | 买卖股票的最好时机(二)25.牛客题解 | 买卖股票的最好时机(四)26.牛客题解 | 二分查找-I27.牛客题解 | 二叉树中的最大路径和28.牛客题解 | 从中序与后序遍历序列构造二叉树29.牛客题解 | 信封嵌套30.牛客题解 | 兑换零钱31.牛客题解 | 分割等和子集32.牛客题解 | 删除相邻数字的最大分数33.牛客题解 | 删除链表的节点34.牛客题解 | 反转链表题目
解题思路
无向图最短路径解题思路(BFS)
1. 问题分析
- 无向图中找最短路径
- 边的权重都是
- 需要处理不连通的情况
- 使用 (广度优先搜索)最适合解决这类问题
2. 解题步骤
-
图的存储
- 使用邻接表存储图
- 每个节点存储其相邻节点的列表
- 因为是无向图,每条边需要存两次
-
BFS实现
- 使用队列存储待访问的节点
- 使用数组记录到每个点的距离
- 使用 数组标记已访问的点
-
具体流程
- 从 号点开始
- 将 号点加入队列,距离设为
- 每次取出队首节点,遍历其相邻节点
- 对未访问的相邻节点,更新距离并加入队列
-
结果判断
- 如果能访问到 号点,输出距离
- 如果不能访问到 号点,输出
3. 注意事项
- 初始化:
- 距离数组初始化为
- 号点的距离初始化为
- 边界处理:
- 检查图是否为空
- 处理孤立点的情况
这种方法适合解决无权图(或权值相等)的最短路径问题,实现简单且效率高。
代码
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
class Solution {
public:
int shortestPath(int n, int m, vector<vector<int>>& edges) {
// 建图
vector<vector<int>> graph(5000 + 1);
for (auto& edge : edges) {
int u = edge[0], v = edge[1];
graph[u].push_back(v);
graph[v].push_back(u);
}
// BFS
vector<int> dist(5000 + 1, -1); // 距离数组初始化为-1
queue<int> q;
q.push(1);
dist[1] = 0;
while (!q.empty()) {
int cur = q.front();
q.pop();
for (int next : graph[cur]) {
if (dist[next] == -1) { // 未访问过
dist[next] = dist[cur] + 1;
q.push(next);
}
}
}
return dist[n]; // 如果不可达,dist[n]就是-1
}
};
int main() {
int n, m;
cin >> n >> m;
vector<vector<int>> edges;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
edges.push_back({u, v});
}
Solution sol;
cout << sol.shortestPath(n, m, edges) << endl;
return 0;
}
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
// 建图
List<List<Integer>> graph = new ArrayList<>(5000 + 1);
for (int i = 0; i <= 5000; i++) {
graph.add(new ArrayList<>());
}
// 读入边
for (int i = 0; i < m; i++) {
int u = sc.nextInt();
int v = sc.nextInt();
graph.get(u).add(v);
graph.get(v).add(u);
}
// BFS
int[] dist = new int[5000 + 1];
Arrays.fill(dist, -1);
Queue<Integer> queue = new LinkedList<>();
queue.offer(1);
dist[1] = 0;
while (!queue.isEmpty()) {
int cur = queue.poll();
for (int next : graph.get(cur)) {
if (dist[next] == -1) {
dist[next] = dist[cur] + 1;
queue.offer(next);
}
}
}
System.out.println(dist[n]);
}
}
from collections import defaultdict, deque
class Solution:
def shortestPath(self, n: int, m: int, edges: list) -> int:
# 建图
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
graph[v].append(u)
# BFS
dist = [-1] * (5000 + 1) # 距离数组初始化为-1
q = deque([1])
dist[1] = 0
while q:
cur = q.popleft()
for next_node in graph[cur]:
if dist[next_node] == -1: # 未访问过
dist[next_node] = dist[cur] + 1
q.append(next_node)
return dist[n]
def main():
n, m = map(int, input().split())
edges = []
for _ in range(m):
u, v = map(int, input().split())
edges.append([u, v])
sol = Solution()
print(sol.shortestPath(n, m, edges))
if __name__ == "__main__":
main()
算法及复杂度分析
- 算法:无向图最短路径,BFS
- 时间复杂度:
- 是节点数
- 是边数
- 空间复杂度:
- 需要距离数组和访问数组
合集:
牛客笔试必刷101题单题解
分类:
牛客笔试必刷101题单题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!