图论
图的存储方式
邻接矩阵
邻接矩阵 使用 二维数组来表示图结构。 邻接矩阵是从节点的角度来表示图,有多少节点就申请多大的二维数组。
有n 个节点,因为节点标号是从1开始的,为了节点标号和下标对齐,申请 n + 1 * n + 1 这么大的二维数组。
1 2 3 4 5 6
| vector<vector<int>> graph(n + 1, vector<int>(n + 1, 0)); while (m--) { cin >> s >> t graph[s][t] = 1; }
|
邻接表
邻接表 使用 数组 + 链表的方式来表示。 邻接表是从边的数量来表示图,有多少边 才会申请对应大小的链表。
邻接表的构造相对邻接矩阵难理解一些。
1 2 3 4 5 6 7
| vector<list<int>> graph(n + 1); while (m--) { cin >> s >> t; graph[s].push_back(t); }
|
深度优先搜索三部曲
- 确认递归函数,参数
1 2 3 4 5 6
| vector<vector<int>> result; vector<int> path;
void dfs (const vector<vector<int>>& graph, int x, int n) {
|
- 确认终止条件
1 2 3 4 5
| if (x == n) { result.push_back(path); return; }
|
- 处理目前搜索节点出发的路径
1 2 3 4 5 6 7
| for (int i = 1; i <= n; i++) { if (graph[x][i] == 1) { path.push_back(i); dfs(graph, i, n); path.pop_back(); } }
|
- 打印结果
1 2 3 4 5 6 7 8
| if (result.size() == 0) cout << -1 << endl; for (const vector<int> &pa : result) { for (int i = 0; i < pa.size() - 1; i++) { cout << pa[i] << " "; } cout << pa[pa.size() - 1] << endl; }
|
例题:所有可能的路径
题目链接:797. 所有可能的路径
邻接矩阵写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <iostream> #include <vector> using namespace std; vector<vector<int>> result; vector<int> path;
void dfs (const vector<vector<int>>& graph, int x, int n) { if (x == n) { result.push_back(path); return; } for (int i = 1; i <= n; i++) { if (graph[x][i] == 1) { path.push_back(i); dfs(graph, i, n); path.pop_back(); } } }
int main() { int n, m, s, t; cin >> n >> m;
vector<vector<int>> graph(n + 1, vector<int>(n + 1, 0));
while (m--) { cin >> s >> t; graph[s][t] = 1; }
path.push_back(1); dfs(graph, 1, n);
if (result.size() == 0) cout << -1 << endl; for (const vector<int> &pa : result) { for (int i = 0; i < pa.size() - 1; i++) { cout << pa[i] << " "; } cout << pa[pa.size() - 1] << endl; } }
|
邻接表写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <iostream> #include <vector> #include <list> using namespace std;
vector<vector<int>> result; vector<int> path;
void dfs (const vector<list<int>>& graph, int x, int n) {
if (x == n) { result.push_back(path); return; } for (int i : graph[x]) { path.push_back(i); dfs(graph, i, n); path.pop_back(); } }
int main() { int n, m, s, t; cin >> n >> m;
vector<list<int>> graph(n + 1); while (m--) { cin >> s >> t; graph[s].push_back(t);
}
path.push_back(1); dfs(graph, 1, n);
if (result.size() == 0) cout << -1 << endl; for (const vector<int> &pa : result) { for (int i = 0; i < pa.size() - 1; i++) { cout << pa[i] << " "; } cout << pa[pa.size() - 1] << endl; } }
|