图论中的“单源”和“全源”
作者:野牛程序员:2025-11-21 14:50:39C++阅读 2271
图论中的“单源”和“全源”
在图论中,“单源”和“全源”是描述最短路径问题时常用的两个概念,关键区别在于起点数量不同。
🔹 单源(Single-Source)
含义:
给定图中一个固定的起点,求这个起点到图中所有其它点的最短路径。
例子:
从节点 A 出发,计算 A→B、A→C、A→D…… 的最短路径。
典型算法:
Dijkstra(权值非负)
Bellman–Ford(可处理负权)
SPFA(Bellman-Ford 的优化版)
BFS(用于无权图)
🔹 全源(All-Pairs)
含义:
求图中任意两个节点之间的最短路径。
不仅仅是某个特定起点,而是整个图的所有点对之间的最短路径。
例子:
计算 A→B、A→C、B→C、B→A…… 等所有点对。
典型算法:
Floyd–Warshall(经典 DP,全源最短路径)
多次运行 Dijkstra(适用于稀疏图)
🔹 简单区分方式
| 名称 | 起点数量 | 求解范围 |
|---|---|---|
| 单源最短路径 | 1 个起点 | 起点 → 所有其他点 |
| 全源最短路径 | 所有点 | 每个点 → 每个点 |
🔹 一个形象理解
单源像是从某个城市出发,查到所有城市的最短路线。
全源像是做一份全国所有城市之间的最短路线地图。
单源最短路径(Dijkstra)
目标:从一个起点出发,求这个点到所有点的最短距离。
特点:适用于非负权图。
单源示例代码
#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;
// 邻接表 graph[u] = (v, w)
vector<pair<int,int> > graph[1005];
int dista[1005];
bool vis[1005];
int main() {
int n, m;
cin >> n >> m; // n个点 m条边
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
graph[u].push_back(make_pair(v, w));
graph[v].push_back(make_pair(u, w)); // 若为无向图
}
int start;
cin >> start;
// 初始化
for (int i = 1; i <= n; i++) dista[i] = INF;
dista[start] = 0;
// Dijkstra 优先队列
priority_queue< pair<int,int>,
vector<pair<int,int> >,
greater<pair<int,int> > > pq;
pq.push(make_pair(0, start));
while (!pq.empty()) {
int u = pq.top().second;
pq.pop();
if (vis[u]) continue;
vis[u] = true;
for (int i = 0; i < graph[u].size(); i++) {
int v = graph[u][i].first;
int w = graph[u][i].second;
if (dista[v] > dista[u] + w) {
dista[v] = dista[u] + w;
pq.push(make_pair(dista[v], v));
}
}
}
// 输出结果
for (int i = 1; i <= n; i++) {
cout << "start -> " << i << " = " << dista[i] << endl;
}
return 0;
}全源最短路径(Floyd)
目标:求任意两个节点之间的最短距离。
特点:适用于有无负权都可(不过不能有负环)。
全源示例代码(Floyd–Warshall)
#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;
// 邻接表 graph[u] = (v, w)
vector<pair<int,int> > graph[1005];
int dista[1005];
bool vis[1005];
int main() {
int n, m;
cin >> n >> m; // n个点 m条边
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
graph[u].push_back(make_pair(v, w));
graph[v].push_back(make_pair(u, w)); // 若为无向图
}
int start;
cin >> start;
// 初始化
for (int i = 1; i <= n; i++) dista[i] = INF;
dista[start] = 0;
// Dijkstra 优先队列
priority_queue< pair<int,int>,
vector<pair<int,int> >,
greater<pair<int,int> > > pq;
pq.push(make_pair(0, start));
while (!pq.empty()) {
int u = pq.top().second;
pq.pop();
if (vis[u]) continue;
vis[u] = true;
for (int i = 0; i < graph[u].size(); i++) {
int v = graph[u][i].first;
int w = graph[u][i].second;
if (dista[v] > dista[u] + w) {
dista[v] = dista[u] + w;
pq.push(make_pair(dista[v], v));
}
}
}
// 输出结果
for (int i = 1; i <= n; i++) {
cout << "start -> " << i << " = " << dista[i] << endl;
}
return 0;
}两者核心区别总结
| 类型 | 目标 | 经典算法 |
|---|---|---|
| 单源最短路径 | 从某点到所有点 | Dijkstra / Bellman-Ford / BFS |
| 全源最短路径 | 所有点到所有点 | Floyd / 多次 Dijkstra |
野牛程序员教少儿编程与信息学奥赛-微信|电话:15892516892

- 上一篇:KMP 算法是什么算法?
- 下一篇:常见服务器环境中“设置拦截对应请求头”的方式
