图论简述+图论考试要点(C++)

图论基本概念

图论是研究图(Graph)的数学理论,图由**顶点(Vertex)边(Edge)**组成,用于表示对象及其关系。

  • 无向图:边无方向,用无序对 (u, v) 表示。
  • 有向图:边有方向,用有序对 (u \\to v) 表示。
  • 权重图:边附带权值,常用于路径优化问题。
  • 常见术语:度(Degree)、路径(Path)、环(Cycle)、连通性(Connectedness)。

图的存储方式(C++实现)

邻接矩阵

适用于稠密图,空间复杂度 O(V\^2)

cpp 复制代码
const int MAX_V = 100;
int adjMatrix[MAX_V][MAX_V]; // 初始化为0或INF
邻接表

适用于稀疏图,空间复杂度 O(V + E)

cpp 复制代码
#include <vector>
vector<int> adjList[MAX_V]; // 无权重
vector<pair<int, int>> weightedAdjList[MAX_V]; // 带权重

图遍历算法

深度优先搜索(DFS)

递归或栈实现,用于连通性检测、拓扑排序等。

cpp 复制代码
bool visited[MAX_V];
void dfs(int u) {
    visited[u] = true;
    for (int v : adjList[u]) {
        if (!visited[v]) dfs(v);
    }
}
广度优先搜索(BFS)

队列实现,用于最短路径(无权图)。

cpp 复制代码
queue<int> q;
bool visited[MAX_V];
void bfs(int start) {
    q.push(start);
    visited[start] = true;
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int v : adjList[u]) {
            if (!visited[v]) {
                visited[v] = true;
                q.push(v);
            }
        }
    }
}

最短路径算法

Dijkstra算法

适用于非负权图,时间复杂度 O((V + E) \\log V)

cpp 复制代码
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
vector<int> dist(MAX_V, INF);
void dijkstra(int start) {
    dist[start] = 0;
    pq.push({0, start});
    while (!pq.empty()) {
        auto [d, u] = pq.top(); pq.pop();
        if (d > dist[u]) continue;
        for (auto [v, w] : weightedAdjList[u]) {
            if (dist[v] > dist[u] + w) {
                dist[v] = dist[u] + w;
                pq.push({dist[v], v});
            }
        }
    }
}
Floyd-Warshall算法

动态规划实现,适用于所有节点对的最短路径,时间复杂度 O(V\^3)

cpp 复制代码
int dist[MAX_V][MAX_V];
void floydWarshall(int V) {
    for (int k = 0; k < V; ++k)
        for (int i = 0; i < V; ++i)
            for (int j = 0; j < V; ++j)
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
}

最小生成树(MST)

Kruskal算法

基于并查集,时间复杂度 O(E \\log E)

cpp 复制代码
struct Edge { int u, v, w; };
vector<Edge> edges;
int parent[MAX_V];

int find(int u) { return parent[u] == u ? u : parent[u] = find(parent[u]); }

int kruskal() {
    sort(edges.begin(), edges.end(), [](Edge a, Edge b) { return a.w < b.w; });
    for (int i = 0; i < MAX_V; ++i) parent[i] = i;
    int total = 0;
    for (Edge e : edges) {
        int pu = find(e.u), pv = find(e.v);
        if (pu != pv) {
            parent[pu] = pv;
            total += e.w;
        }
    }
    return total;
}
Prim算法

优先队列实现,时间复杂度 O(E \\log V)

cpp 复制代码
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
bool inMST[MAX_V];
int prim() {
    pq.push({0, 0});
    int total = 0;
    while (!pq.empty()) {
        auto [w, u] = pq.top(); pq.pop();
        if (inMST[u]) continue;
        inMST[u] = true;
        total += w;
        for (auto [v, weight] : weightedAdjList[u]) {
            if (!inMST[v]) pq.push({weight, v});
        }
    }
    return total;
}

拓扑排序

适用于有向无环图(DAG),基于DFS或BFS(Kahn算法)。

cpp 复制代码
vector<int> topoSort(int V) {
    vector<int> inDegree(V, 0), result;
    for (int u = 0; u < V; ++u)
        for (int v : adjList[u]) inDegree[v]++;
    queue<int> q;
    for (int u = 0; u < V; ++u)
        if (inDegree[u] == 0) q.push(u);
    while (!q.empty()) {
        int u = q.front(); q.pop();
        result.push_back(u);
        for (int v : adjList[u]) {
            if (--inDegree[v] == 0) q.push(v);
        }
    }
    return result.size() == V ? result : vector<int>(); // 检查环
}

关键考点总结

  1. 基础概念:图的分类、术语(度、连通分量等)。
  2. 存储与遍历:邻接表/矩阵的选择,DFS/BFS的应用场景。
  3. 算法实现:Dijkstra、Floyd、Kruskal、Prim的代码模板。
  4. 拓扑排序:DAG的判定与排序方法。
  5. 复杂度分析:各算法的时间/空间复杂度比较。

建议结合实际问题(如LeetCode、OJ题目)练习代码实现。

相关推荐
我能坚持多久5 分钟前
优选算法——专题一双指针(上):附四道例题详解
c++·学习·算法
Tim_1010 分钟前
【C++】023、移动语义&深拷贝
开发语言·c++·算法
ShineWinsu26 分钟前
对于C++中unordered_map的详细介绍
数据结构·c++·算法·面试·stl·哈希表·unordered_map
东东最爱敲键盘30 分钟前
day3.c++函数与预处理 string
c++·算法
djjjx.41 分钟前
【 C++ 】stack、queue、优先级队列、仿函数、容器适配器
开发语言·c++
lingran__1 小时前
C++ 高阶数据结构:AVL 树万字详解|原理、四种旋转、key‑value 实现、调试校验、set/map/红黑树 底层前置知识
数据结构·c++·二叉搜索树·平衡二叉树·avl树·红黑树前置
爱和冰阔落1 小时前
【Linux】两个毫无关系的进程怎么通信?命名管道 FIFO 从原理到 Server/Client 实战
android·linux·数据库·c++·vim
码匠许师傅9 小时前
【C++ 面试真题】C++ 的 const 和 constexpr 有什么区别?
c++·面试
wabs66612 小时前
关于图论【最短路径之Dijkstra算法(堆优化版)|卡码网47.参加科学大会的思考】
数据结构·算法·图论·优先级队列·邻接表·小顶堆·卡码网
果果燕12 小时前
实习笔记(一):NFS、Samba、VNC、Git、CMake、systemd、内核、交叉编译
linux·arm开发·c++·笔记·git