广度优先搜索(BFS)
BFS介绍
树和图的广度优先遍历都需要使用一个队列来实现。
在过程中,我们不断从队头取出一个节点x,对于x面对的多条分支,把沿着每条分支到达的下一个尚未访问过的节点插入队尾。
BFS有两个重要性质:
- 在访问完所有的第 i i i 层节点后,才会开始访问第 i + 1 i+1 i+1 层节点。
- 任意时刻,队列中至多有两个层次的节点。若其中一部分节点属于第 i i i 层,那么另一部分节点就属于第 i + 1 i+1 i+1 层,并且所有第 i i i 层节点排在第 i + 1 i+1 i+1 层节点之前。也就是说,广度优先遍历队列中的元素关于层次满足“两段性”和“单调性”。
拓扑排序
参考代码如下:
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++, d[b]++;
}
void topsort()
{
queue<int> q;
for(int i = 1; i <= n; i++)
if(!d[i]) q.push(i);
while(q.size()) {
int u = q.front(); q.pop();
top_q[++cnt] = u;
for(int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if(--d[v] == 0) q.push(v);
}
}
}
例题
可达性统计 (CH2001)
代码实现
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <bitset>
using namespace std;
const int N = 3e4 + 10;
int n, m;
int h[N], e[N], ne[N], d[N], idx;
int q[N];
int a[N], cnt;
bitset<N> f[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++, d[b] ++;
}
void topsort()
{
int hh = 0, tt = -1;
for(int i = 1; i <= n; i++)
if(d[i] == 0) q[++tt] = i;
while(hh <= tt)
{
int u = q[hh ++];
a[cnt++] = u;
for(int i = h[u]; ~i; i = ne[i])
if(--d[e[i]] == 0) q[++ tt] = e[i];
}
}
int main()
{
memset(h, -1, sizeof h);
cin >> n >> m;
while(m--)
{
int a, b;
cin >> a >> b;
add(a, b);
}
topsort();
for(int i = cnt - 1; i >= 0; i--)
{
int u = a[i];
f[u][u] = 1;
for(int j = h[u]; ~j; j = ne[j])
f[u] |= f[e[j]];
}
for(int i = 1; i <= n; i++)
cout << f[i].count() << endl;
return 0;
}
Bloxorz (POJ3322)
详情见蓝书。
代码实现
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 510;
struct rec { int x, y, lie; };
int n, m;
char s[N][N];
int d[N][N][3];
rec st, ed;
const int next_x[3][4] = { {0, 0, -2, 1}, {0, 0, -1, 1}, {0, 0, -1, 2} };
const int next_y[3][4] = { {-2, 1, 0, 0}, {-1, 2, 0, 0}, {-1, 1, 0, 0} };
const int next_lie[3][4] = { {1, 1, 2, 2}, {0, 0, 1, 1}, {2, 2, 0, 0} };
inline bool valid(int x, int y)
{
return x >= 0 && x < n && y >= 0 && y < m;
}
inline bool valid(rec t)
{
int x = t.x, y = t.y, lie = t.lie;
if(!valid(x, y)) return false;
if(s[x][y] == '#') return false;
if(lie == 0 && s[x][y] != '.') return false;
if(lie == 1 && s[x][y + 1] == '#') return false;
if(lie == 2 && s[x + 1][y] == '#') return false;
return true;
}
void parse_st_ed()
{
int dx[4] = {0, 0, -1, 1}, dy[4] = {-1, 1, 0, 0};
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
if(s[i][j] == 'O') {
ed.x = i, ed.y = j, ed.lie = 0, s[i][j] = '.';
}
else if(s[i][j] == 'X') {
for(int k = 0; k < 4; k++) {
int x = i + dx[k], y = j + dy[k];
if(valid(x, y) && s[x][y] == 'X') {
st.x = min(i, x), st.y = min(j, y);
st.lie = k < 2 ? 1 : 2;
s[i][j] = s[x][y] = '.';
break;
}
}
if(s[i][j] == 'X') st.x = i, st.y = j, st.lie = 0;
}
}
int bfs()
{
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
for(int k = 0; k < 3; k++)
d[i][j][k] = -1;
queue<rec> q;
q.push(st);
d[st.x][st.y][st.lie] = 0;
while(q.size()) {
rec now = q.front(); q.pop();
if(now.x == ed.x && now.y == ed.y && now.lie == ed.lie) return d[now.x][now.y][now.lie];
for(int i = 0; i < 4; i++) {
rec next = {now.x + next_x[now.lie][i], now.y + next_y[now.lie][i], next_lie[now.lie][i]};
if(!valid(next)) continue;
int x = next.x, y = next.y, lie = next.lie;
if(d[x][y][lie] == -1) {
d[x][y][lie] = d[now.x][now.y][now.lie] + 1;
q.push(next);
}
}
}
return -1;
}
int main()
{
while(scanf("%d %d", &n, &m) != EOF && n)
{
for(int i = 0; i < n; i++) scanf("%s", s[i]);
parse_st_ed();
int ans = bfs();
if(ans == -1) puts("Impossible");
else printf("%d\n", ans);
}
return 0;
}
矩阵距离 (CH2501)
题目描述:
给定一个 N N N 行 M M M 列的 01 01 01 矩阵 A A A, A [ i ] [ j ] A[i][j] A[i][j] 与 A [ k ] [ l ] A[k][l] A[k][l] 之间的曼哈顿距离定义为:
d i s t ( A [ i ] [ j ] , A [ k ] [ l ] ) = ∣ i − k ∣ + ∣ j − l ∣ d i s t ( A [ i ] [ j ] , A [ k ] [ l ] ) = ∣ i − k ∣ + ∣ j − l ∣ dist(A[i][j],A[k][l])=|i−k|+|j−l|dist(A[i][j],A[k][l])=|i−k|+|j−l| dist(A[i][j],A[k][l])=∣i−k∣+∣j−l∣dist(A[i][j],A[k][l])=∣i−k∣+∣j−l∣
输出一个 N N N 行 M M M 列的整数矩阵 B B B,其中:
B [ i ] [ j ] = m i n 1 ≤ x ≤ N , 1 ≤ y ≤ M , A [ x ] [ y ] = 1 d i s t ( A [ i ] [ j ] , A [ x ] [ y ] ) B[i][j]=min1≤x≤N,1≤y≤M,A[x][y]=1dist(A[i][j],A[x][y])