当前位置:首页C++ > 正文

图论中的“单源”和“全源”

作者:野牛程序员: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
野牛程序员教少儿编程与信息学竞赛-微信|电话:15892516892
  • 图论中的“单源”和“全源”
  • 相关推荐

    最新推荐

    热门点击