Khoá học C++ nâng cao
Bài học: Lý Thuyết Đồ Thị Cơ Bản & Nâng Cao
🏆 +100 XP tiềm năng Thoát

Lý Thuyết Đồ Thị Cơ Bản & Nâng Cao

2 khối nội dung 45 phút học tập MỞ BẢNG TRẮNG

Lý Thuyết Đồ Thị Cơ Bản & Nâng Cao

Nội dung bài học

1. Khái niệm & biểu diễn đồ thị trong lập trình thi đấu

Lý thuyết đồ thị (Graph Theory) là mô hình trừu tượng mô tả mối quan hệ (các cạnh $E$) giữa các đối tượng (các đỉnh $V$).

Các phương pháp biểu diễn đồ thị chuẩn:

  • Danh sách kề (vector<vector<int>> adj): Tiết kiệm bộ nhớ $\mathcal{O}(V + E)$, duyệt các đỉnh kề nhanh nhất $\implies$ Chuẩn thi đấu bắt buộc.
  • Ma trận kề (vector<vector<int>> matrix): Tốn bộ nhớ $\mathcal{O}(V^2)$, chỉ dùng khi $V \le 1000$.
  • Danh sách cạnh (vector<vector<int>> edges): Dùng trong các thuật toán cây khung nhỏ nhất (Kruskal, Bellman-Ford).

2. Hai thuật toán duyệt đồ thị cốt lõi: BFS & DFS

2.1. Tìm kiếm theo chiều sâu (Depth-First Search — DFS)

  • Duyệt đi sâu vào từng nhánh theo cơ chế đệ quy (Stack ngầm định).
  • Ứng dụng: Đếm thành phần liên thông, phát hiện chu trình (Cycle Detection), sắp xếp Tô-pô (Topological Sort), kiểm tra đồ thị hai phía (Bipartite Graph).
void dfs(int u, const vector<vector<int>> &adj, vector<bool> &visited) {
    visited[u] = true;
    for (int v : adj[u]) {
        if (!visited[v]) dfs(v, adj, visited);
    }
}

2.2. Tìm kiếm theo chiều rộng (Breadth-First Search — BFS)

  • Duyệt theo từng lớp khoảng cách lan tỏa bằng Hàng đợi (queue<int>).
  • Tính chất vàng: BFS luôn tìm ra đường đi ngắn nhất (ít cạnh nhất) trên đồ thị không có trọng số hoặc đồ thị lưới 2D.
vector<int> bfs_shortest_path(int start_node, int n, const vector<vector<int>> &adj) {
    vector<int> dist(n + 1, -1);
    queue<int> q;

    dist[start_node] = 0;
    q.push(start_node);

    while (!q.empty()) {
        int u = q.front();
        q.pop();

        for (int v : adj[u]) {
            if (dist[v] == -1) {
                dist[v] = dist[u] + 1;
                q.push(v);
            }
        }
    }
    return dist;
}

Thuật toán Tarjan tìm Khớp và Cầu

3. Thuật toán Dijkstra

Khi các cạnh có trọng số $W_e \ge 0$, ta sử dụng thuật toán Dijkstra kết hợp Hàng đợi ưu tiên (Min-Heap) đạt độ phức tạp $\mathcal{O}((V + E) \log V)$:

#include <bits/stdc++.h>
using namespace std;

const long long INF = 1e18;

vector<long long> dijkstra(int start_node, int n, const vector<vector<pair<int, long long>>> &adj) {
    vector<long long> dist(n + 1, INF);
    // Min-heap lưu {khoảng_cách, đỉnh}
    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;

    dist[start_node] = 0;
    pq.push({0, start_node});

    while (!pq.empty()) {
        auto [d, u] = pq.top();
        pq.pop();

        if (d > dist[u]) continue; // Bỏ qua trạng thái cũ

        for (auto &edge : adj[u]) {
            int v = edge.first;
            long long w = edge.second;
            if (dist[u] + w < dist[v]) {
                dist[v] = dist[u] + w;
                pq.push({dist[v], v});
            }
        }
    }
    return dist;
}

4. Ranh giới áp dụng

Loại Đồ Thị Mục Tiêu Thuật Toán Tối Ưu Độ Phức Tạp
Không trọng số / Trọng số 1 Đường đi ngắn nhất BFS $\mathcal{O}(V + E)$
Trọng số $0$ và $1$ Đường đi ngắn nhất 0-1 BFS (dùng deque) $\mathcal{O}(V + E)$
Trọng số không âm ($W \ge 0$) Đường đi ngắn nhất Dijkstra + Min-Heap $\mathcal{O}((V + E) \log V)$
Đồ thị có hướng không chu trình (DAG) Lập lịch / Thứ tự ưu tiên Sắp xếp Tô-pô (Kahn / DFS) $\mathcal{O}(V + E)$
Đồ thị lưới 2D Loang màu / Tìm miền liên thông Flood Fill (DFS / BFS) $\mathcal{O}(R \times C)$

1
A
B
C
D
2
A
B
C
D

Bài tập lập trình vận dụng

26 Bài tập thực hành

Nhấn vào nút "Làm bài" bên dưới để mở giao diện làm bài trực tuyến (Online Judge) và thực hiện viết mã nguồn cho bài tập này.

Đường đi ngắn nhất Dijkstra
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Đường đi ngắn nhất mê cung 2d bằng BFS
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Kiểm tra đồ thị hai phía (bipartite graph coloring)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Sắp xếp tô-pô lập lịch khóa học (topological sort)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Dijkstra tìm đường đi ngắn nhất chuẩn
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Mê cung trọng số 0 và 1 (0-1 BFS)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Cây khung nhỏ nhất (MST Kruskal với DSU)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tìm khớp và cầu trên đồ thị (tarjan's bridge & articulation)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Dijkstra trên đồ thị mở rộng trạng thái (k lần dùng vé miễn phí)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Thành phần liên thông mạnh (scc tarjan/kosaraju)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tìm tổ tiên chung gần nhất (LCA binary lifting)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Dijkstra trên đồ thị mở rộng trạng thái (k lần dùng vé)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Multi-source BFS lan tỏa dịch bệnh / cháy rừng
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Đường đi Euler & chu trình Euler (Hierholzer)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tìm chu trình âm bằng bellman-ford / spfa
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Luồng cực đại trong mạng (max flow dinic algorithm)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
BFS do thi trong so 0 1
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tarjan tim khop va cau
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tarjan thanh phan lien thong manh scc
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Chu trinh Euler Hierholzer
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Dijkstra do thi nhieu tang k ve mien phi
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Dinh to nho nhat Kruskal DSU
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Bellman-Ford chu trinh am
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Floyd-Warshall moi cap dinh
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
LCA to tien chung gan nhat binary lifting
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Dem so duong di topo DAG
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài