dfs, bfs, 图和树问题 (一)
1.图表示
Adjacent list
vector<int> adj[N]
weighted graph
vector<pair<int,int>> adj[N];
adjacent matrix
int adj[N][N];
edge list
vector<pair<int, int>> edges;
weighted edge list
vector<tuple<int, int, int>> edges;
2.图遍历
dfs
vector<int> adj[N];
bool visited[N];
void dfs(int s) {
if (visited[s]) return;
visited[s] = true;
// process node s
for (auto u: adj[s]) {
dfs(u);
}
}
acwing842.排列数字
dfs + visited + 回溯(剪枝 + 恢复现场)
https://www.acwing.com/problem/content/844/
#include <bits/stdc++.h>
#define N 7
using namespace std;
int n;
int path[N];
bitset<9> bs {};
void dfs(int k) {
if (k==n) {
for (int i=0; i<k && path[i] != 0; i++) {
cout << path[i] << " ";
}
cout << "\n";
return;
} else {
for (int j=1; j<=n; j++) {
if (bs[j]) continue;
bs[j] = true;
path[k] = j;
dfs(k+1);
path[k] = 0;
bs[j] = false;
}
}
}
int main() {
cin >> n;
dfs(0);
}
acwing843.n皇后
https://www.acwing.com/problem/content/845/
对角线的处理 + 行坐标->len
反对角线 -> 同条反对角线上col+row相等
对角线 -> 同个对角线上n-row+col相等(相当于回到截距,但是和坐标不同,col往下是增大,所以要+col)
ttl -> 需要用行坐标代表len(greedy)
#include <bits/stdc++.h>
#define N 20
using namespace std;
int n;
int visited_row[N], visited_col[N], visited_dg[N], visited_udg[N];
set<pair<int, int>> paths;
void dfs(int len) {
if (len == n) {
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
if (paths.find({i, j}) != paths.end()) {
cout << "Q";
} else
cout << ".";
}
cout << "\n";
}
cout << "\n";
return;
}
else
for (int row=len; row<n; row ++ ) {
for (int col=0; col<n; col++) {
if (visited_row[row] || visited_col[col] || visited_dg[col+row] || visited_udg[n-row+col] ) continue;
visited_row[row] = visited_col[col] = visited_dg[col+row] = visited_udg[n-row+col] = true;
paths.insert({row, col});
dfs(len+1);
visited_row[row] = visited_col[col] = visited_dg[col+row] = visited_udg[n-row+col] = false;
paths.erase({row, col});
}
}
}
int main() {
cin >> n;
dfs(0);
}
#include <bits/stdc++.h>
#define N 20
using namespace std;
int n;
int visited_col[N], visited_dg[N], visited_udg[N];
set<pair<int, int>> paths;
void dfs(int row) {
if (row == n) {
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
if (paths.find({i, j}) != paths.end()) {
cout << "Q";
} else
cout << ".";
}
cout << "\n";
}
cout << "\n";
return;
}
else
for (int col=0; col<n; col++) {
if (visited_col[col] || visited_dg[col+row] || visited_udg[n-row+col] ) continue;
visited_col[col] = visited_dg[col+row] = visited_udg[n-row+col] = true;
paths.insert({row, col});
dfs(row+1);
visited_col[col] = visited_dg[col+row] = visited_udg[n-row+col] = false;
paths.erase({row, col});
}
}
int main() {
cin >> n;
dfs(0);
}
bfs
queue<int> q;
bool visited[N];
void bfs(int s) {
if (visited[s]) return;
visited[s] = true;
while(!q.empty()) {
int s = q.front();q.pop();
for (auto u: adj[s]) {
if (visited[u]) continue;
visited[u] = true;
q.push(u);
}
}
}
acwing844走迷宫
https://www.acwing.com/problem/content/846/
分层形bfs
#include <bits/stdc++.h>
#define N 101
using namespace std;
int mat[N][N];
int n, m, len;
int dx[4] = {0 ,1, 0, -1};
int dy[4] = {1, 0, -1, 0};
int main() {
cin >> n >> m;
for (int i=0; i<n; i++) {
for (int j=0; j<m; j++) {
int a;
cin >> a;
mat[i][j] = a;
}
}
// bfs();
queue<pair<int,int>> q {{make_pair(0,0)}};
len = 0;
while (!q.empty()) {
int lenq = q.size();
len++;
for (int j=0; j<lenq; j++) {
auto [x, y] = q.front(); q.pop();
for (int i=0; i<4; i++) {
int new_x = x + dx[i], new_y = y+dy[i];
if (new_x >= 0 && new_x < n && new_y >= 0 && new_y < m && !mat[new_x][new_y]) {
mat[new_x][new_y] = 1;
if (new_x == n-1 && new_y == m-1) {
cout << len;
return 0;
}
q.push({new_x, new_y});
}
}
}
}
}
acwing845八数码
https://www.acwing.com/problem/content/description/847/
直接暴力bfs + map
向量和矩阵坐标的转换 -> x = idx/3; y=idx%3;
矩阵转回向量坐标 -> idx = x*3 + y;
#include <bits/stdc++.h>
using namespace std;
unordered_map<string, int> str_dist {};
string endstr {"12345678x"};
int x_idx, dx[4]{0,1,0,-1},dy[4]{1,0,-1,0};
int bfs(string str) {
if (endstr == str) return 0;
int dist=0;
queue<pair<string, int>> q{{make_pair(str, x_idx)}};
while(q.size()) {
int lenQ = q.size();dist++;
for (int i=0; i<lenQ; i++) {
auto [cur_str, idx] = q.front(); q.pop();
int x=idx/3, y=idx%3;
for (int j=0; j<4; j++) {
int new_x = x+dx[j], new_y=y+dy[j];
if (new_x>=0 && new_x<3 && new_y<3 && new_y>=0) {
swap(cur_str[idx], cur_str[new_x*3+new_y]);
if (str_dist.find(cur_str) == str_dist.end()) {
if (cur_str == endstr) return dist;
str_dist[cur_str] = dist;
q.push(make_pair(cur_str, new_x*3+new_y));
}
swap(cur_str[idx], cur_str[new_x*3+new_y]);
}
}
}
}
return -1;
}
int main() {
string str;
for (int i=0; i<9; i++) {
char a;
cin >> a;
if (a=='x') x_idx= i;
str += a;
}
cout << bfs(move(str));
}
康托展开优化版
应用
- Connectivity check
- Finding cycles
- Bipartiteness check(两色法)
拓扑排序
Shortest paths
unweighted graph - bfs