DFS与BFS
用$Stack$递归,空间$O(h)$,不具有最短性
用$Queue$,空间$O(2^h)$,“最短路”
回溯、剪枝
在矩阵中4个方向遍历
1
| int dx[] = {1,0,-1,0},y = {0,1,0,-1};
|
防止走相反的方向导致搜索回溯
1
| if(i ^ 2 == d) continue;
|
8个方向遍历
1 2
| int dx[8] = {-1, -1, -1, 0, 1, 1, 1, 0}; int dy[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
|
防止走相反的方向导致搜索回溯
1
| if(i ^ 4 == d) continue;
|
树和图的存储
树是特殊的无环连通图
有向图$a \to b$
- 邻接矩阵 $g[a][b]$
- 邻接表,用链表储存点$i$可以到达的点
1 2 3 4 5 6 7 8 9 10 11 12
| int h[N], e[N], ne[N], idx;
void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ; }
idx = 0; memset(h, -1, sizeof h);
|
树和图的遍历
时间复杂度$O(n+m)$,n表示点数,m表示边数
1 2 3 4 5 6 7 8 9 10
| int dfs(int u) { st[u] = true;
for (int i = h[u]; i != -1; i = ne[i]) { int j = e[i]; if (!st[j]) dfs(j); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| queue<int> q; st[1] = true; q.push(1);
while (q.size()) { int t = q.front(); q.pop();
for (int i = h[t]; i != -1; i = ne[i]) { int j = e[i]; if (!st[j]) { st[j] = true; q.push(j); } } }
|
拓扑排序
时间复杂度$O(n+m)$,n表示点数,m表示边数
有向无环图一定可以拓扑排序,序列可能不唯一
入度、出度:有多少条边指向自己/从自己这里指出去
- 将入度为0的点入队
- 宽搜,枚举队头的所有出边$t \to j$,删掉$t \to j$,$t$的出度减一
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
| bool topsort() { int hh = 0, tt = -1;
for (int i = 1; i <= n; i ++ ) if (!d[i]) q[ ++ tt] = i;
while (hh <= tt) { int t = q[hh ++ ];
for (int i = h[t]; i != -1; i = ne[i]) { int j = e[i]; d[j]--; if (d[j] == 0) q[ ++ tt] = j; } }
return tt == n - 1; }
|
一个有向无环图至少有一个入度为0的点