一.邻接表的使用方法
使用一个支持动态增加元素的数据结构构成的数组,如 vector<int> adj[n + 1]
来存边,其中 adj[u]
存储的是点 的所有出边的相关信息(终点、边权等)。
二.例题
1.树的遍历
题目描述
给定一棵大小为n,根为1的树,求出其dfs序、bfs序。
请将所有出点按照编号从小到大排序后进行遍历。
解释:dfs为深度优先搜索,bfs为宽度优先搜索。
输入格式
一个整数n,表示点的个数。(1≤n≤50)
接下来一行n−1个整数,第i个数字fai表示点i的父亲。(1≤fai≤n)
输出格式
第一行输出dfs序,第二行输出bfs序。
样例输入1
4
1 1 2
样例输出1
1 2 4 3
1 2 3 4
代码示例
#include <bits/stdc++.h>
using namespace std;
const int N = 60;
int root[N], n;
vector<int> g[N];
void dfs(int x) {
cout << x << ' ';
for(auto &y : g[x]) dfs(y);
/*for(int j = 0; j < g[x].size(); j++) {
int y = g[x][j];
dfs(y);// 进行操作,比如输出或者其他处理
}*/
}
void bfs(int rt) {
queue<int> q;
q.push(rt);
while(q.size()) {
int x = q.front(); q.pop();
cout << x << ' ';
for(auto &y : g[x]) q.push(y);
}
}
int main() {
cin >> n;
for(int i = 2; i <= n; i++) cin >> root[i];
for(int i = 2; i <= n; i++) g[root[i]].push_back(i);
for(int i = 1; i <= n; i++) sort(g[i].begin(), g[i].end());
dfs(1);
cout << '\n';
bfs(1);
return 0;
}
2.图的遍历
题目描述
给定一个n个点m条边的有向图,图中可能存在重边和自环,点的编号为1~n。
你需要求出从点1出发,能够到达的所有点。
输入描述
第一行:两个整数n,m,分别表示有向图的点数、边数。(1≤n,m≤)
接下来m行:每行两个整数ui,vi,表示存在一条从ui到vi的有向边。(1≤ui,vi≤n)
输出描述
共一行,从小到大输出1号点能够到达的点的编号。
输入样例1
5 3
1 2
2 4
4 5
输出样例1
1 2 4 5
题目分析
由于本题可能存在自环,故而需要特判;(无权值的重边忽略即可,不影响做题);然后从1号点开始深搜即可。
代码示例
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
vector<int> g[N];
bitset<N> st; //状态数组
void dfs(int x) {
if(st[x]) return ;
st[x] = 1;
for(auto &y : g[x]) dfs(y);
}
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m; cin >> n >> m;
int u, v;
for(int i = 1; i <= m; i++) {
cin >> u >> v;
if(u != v)g[u].push_back(v);//判断是否为自环,若为自环,不入数组
}
dfs(1);
for(int i = 1; i <= n; i++) if(st[i]) cout << i << ' ';//dfs遍历顺序即为由小到大的顺序
return 0;
}