题目链接
题目描述
给定由 个顶点、
条边构成的有向赋权图(不一定连通),边权为非负整数。给定起点
,依次输出从
到每个顶点的最短路径长度;若不可达输出
,到自身输出
。允许重边,无自环。
解题思路
- 非负权最短路 = 堆优化 Dijkstra:对于非负边权,采用 Dijkstra 算法配合优先队列(小根堆)可在
时间内求出单源最短路。
- 做法:
- 建邻接表。距离数组
初始为
,
。
- 用小根堆按当前最短距离取出顶点
,若弹出的距离大于已知
则跳过;否则对每条出边
进行松弛:若
,则更新并入堆。
- 结束后,
的顶点输出
。
- 建邻接表。距离数组
- 细节:
- 边权可能为
,Dijkstra 依然适用。
- 建议使用 64 位整型存储距离,避免累加溢出。
- 边权可能为
代码
#include <bits/stdc++.h>
using namespace std;
using int64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, s;
if (!(cin >> n >> m >> s)) return 0;
vector<vector<pair<int,int>>> g(n + 1);
for (int i = 0; i < m; ++i) {
int u, v, w; cin >> u >> v >> w;
g[u].push_back({v, w});
}
const long long INF = (1LL << 62);
vector<long long> dist(n + 1, INF);
priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;
dist[s] = 0;
pq.push({0, s});
while (!pq.empty()) {
auto [d, u] = pq.top(); pq.pop();
if (d != dist[u]) continue; // 过期状态
for (auto [v, w] : g[u]) {
long long nd = d + w;
if (nd < dist[v]) {
dist[v] = nd;
pq.push({nd, v});
}
}
}
for (int i = 1; i <= n; ++i) {
if (i > 1) cout << ' ';
cout << (dist[i] == INF ? -1 : (long long)dist[i]);
}
cout << '\n';
return 0;
}
import java.util.*;
public class Main {
static class Edge { int v, w; Edge(int v, int w){ this.v=v; this.w=w; } }
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int s = sc.nextInt();
List<Edge>[] g = new ArrayList[n + 1];
for (int i = 1; i <= n; i++) g[i] = new ArrayList<>();
for (int i = 0; i < m; i++) {
int u = sc.nextInt(), v = sc.nextInt(), w = sc.nextInt();
g[u].add(new Edge(v, w));
}
final long INF = 1L << 62;
long[] dist = new long[n + 1];
Arrays.fill(dist, INF);
PriorityQueue<long[]> pq = new PriorityQueue<>(Comparator.comparingLong(a -> a[0]));
dist[s] = 0;
pq.add(new long[]{0L, s});
while (!pq.isEmpty()) {
long[] cur = pq.poll();
long d = cur[0];
int u = (int)cur[1];
if (d != dist[u]) continue;
for (Edge e : g[u]) {
long nd = d + e.w;
if (nd < dist[e.v]) {
dist[e.v] = nd;
pq.add(new long[]{nd, e.v});
}
}
}
StringBuilder out = new StringBuilder();
for (int i = 1; i <= n; i++) {
if (i > 1) out.append(' ');
out.append(dist[i] == INF ? -1 : dist[i]);
}
System.out.println(out);
}
}
import sys
import heapq
data = sys.stdin.read().strip().split()
it = iter(data)
n = int(next(it)); m = int(next(it)); s = int(next(it))
g = [[] for _ in range(n + 1)]
for _ in range(m):
u = int(next(it)); v = int(next(it)); w = int(next(it))
g[u].append((v, w))
INF = 1 << 62
dist = [INF] * (n + 1)
dist[s] = 0
pq = [(0, s)]
while pq:
d, u = heapq.heappop(pq)
if d != dist[u]:
continue
for v, w in g[u]:
nd = d + w
if nd < dist[v]:
dist[v] = nd
heapq.heappush(pq, (nd, v))
print(' '.join(str(-1 if dist[i] == INF else dist[i]) for i in range(1, n + 1)))
算法及复杂度
- 算法:堆优化 Dijkstra,使用小根堆维护当前最短的候选顶点,进行松弛更新。
- 时间复杂度:
。
- 空间复杂度:
。