什么是图:把世界抽象成点和线

地图上城市之间有公路相连;社交网络里你和朋友互相关注;网页之间用超链接跳转。这些看似不同的场景,底层都是同一个数学结构——图(Graph)。

图由两部分组成:顶点(Vertex)表示城市/人/网页,边(Edge)表示公路/好友关系/超链接。边可以有方向(你关注他,他不一定关注你),也可以有权重(公路长度、好友亲密度)。

图论就是研究这种"点和线"结构的数学分支。竞赛里大量题目本质上就是在图上做搜索、找路径、算连通性。

把实际问题抽象成图,问题就解决了一半。
本文核心知识点
  • 图顶点 + 边的组合。
  • 邻接表用 vector 数组存图。
  • DFS深度优先,一条路走到底再回头。
  • BFS广度优先,一圈圈扩散求最短路。
图论入门配图:蓝色渐变背景上多个发光节点由曲线连接成网络,一条金色高亮路径连接两个远端节点,旁边有放大镜、分支树和圆圈队列
节点、边、最短路:图论的三个核心意象。

怎么存图:邻接表与邻接矩阵

电脑怎么存一张图?两种方式:

邻接矩阵:用一个二维数组 g[i][j] 表示 i 和 j 之间有没有边。优点是判断两点间有没有边只要 O(1);缺点是 n 个点要开 n 的平方个空间,n=10000 时内存不够。

邻接表:用一个 vector 数组,g[i] 存着 i 所有邻居的列表。n=10000 只有边数个空间,竞赛里最常用。

#include <vector>
using namespace std;

vector<int> g[100005];   // 邻接表

void addEdge(int u, int v) {
    g[u].push_back(v);
    g[v].push_back(u);   // 无向图要加两次
}

入门阶段先掌握邻接表,邻接矩阵只在 n 很小(n≤500)时用。

DFS 深度优先:一条路走到黑

DFS(Depth-First Search)的思路:从起点出发,选一个邻居走过去,再选那个点的一个邻居继续走,直到走不动了就回头换路。就像走迷宫,沿着一条路一直走到死胡同,再退回来走另一条。

bool visited[100005];

void dfs(int u) {
    visited[u] = true;
    cout << u << " ";
    for (int v : g[u]) {
        if (!visited[v]) {
            dfs(v);
        }
    }
}

// 调用: dfs(1);

关键是 visited 数组,标记哪些点已经走过,防止无限循环。DFS 适合判断连通性(两个点在不在一起)、判断有没有环。

BFS 广度优先:一圈一圈扩散

BFS(Breadth-First Search)的思路:从起点开始,先访问所有距离 1 的点,再访问距离 2 的,再访问距离 3 的……一圈一圈向外扩散。就像往水里扔石头,波纹一圈圈扩大。

#include <queue>

int dist[100005];
bool visited[100005];

void bfs(int start) {
    queue<int> q;
    q.push(start);
    visited[start] = true;
    dist[start] = 0;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int v : g[u]) {
            if (!visited[v]) {
                visited[v] = true;
                dist[v] = dist[u] + 1;
                q.push(v);
            }
        }
    }
}

BFS 用队列实现。它的核心优势是:在无权图上,BFS 第一次访问到某个点时,走的就是最短路径。

最短路:BFS 求无权图最短步数

"无权图"就是每条边长度都是 1。这种图上,从起点到终点最少要走几步?BFS 天然解决这个问题——dist[v] 存的就是起点到 v 的最短步数。

举个例子:迷宫里从左上角走到右下角,每步可以上下左右走一格,最少几步?把每个格子看成一个点,相邻格子之间连边,跑一次 BFS,dist[终点] 就是答案。

如果边有权重(公路长度不同),BFS 就不够用了,要用 Dijkstra 算法。那是图论进阶内容,入门阶段先把无权图 BFS 练熟。

本节用到的核心结构
  • 邻接表vector 数组存图。
  • visited防止重复访问。
  • queueBFS 的核心容器。
  • dist最短步数。