洛谷P5318 【深基18.例3】查找文献(c嘎嘎)
题目链接:P5318 【深基18.例3】查找文献 - 洛谷 | 计算机科学教育新生态
题目难度:普及—
题目描述:小 K 喜欢翻看洛谷博客获取知识。,每篇文章可能会有若干个(也有可能没有)参考文献的链接指向别的博客文章,帮助小 K 设计一种方法,使小 K 可以不重复、不遗漏的看完所有他能看到的文章,请对这个图分别进行 DFS 和 BFS,并输出遍历结果。如果有很多篇文章可以参阅,请先看编号较小的那篇(因此你可能需要先排序)。(如下图)
输入格式
共 m+1 行,第 1 行为 2 个数,n 和 m,分别表示一共有 n(n≤105) 篇文章(编号为 1 到 n)以及m(m≤106) 条参考文献引用关系。
输出格式
共 2 行。 第一行为 DFS 遍历结果,第二行为 BFS 遍历结果。
输入输出样例
解题思路:本题很直接就是要你遍历一个图然后输出DFS和BFS后的结果,对于本题我们使用邻接表(不用邻接矩阵原因:n<1e5),本题要我们要排序,我们用vectoe来存每个节点所能到达的边然后从小到达排序。
DFS 和 BFS介绍:学过数据结构我们都知道DFS通俗来说是从图的一个点出发,选择下一个点再以下一个点向下选择直到你选择的点没有可以选择的点了,BFS,用通俗的话来说,就是你从图中的一个节点出发,其有几个子节点,你会先将这所有的子节点遍历,再挑其中的一个子节点,遍历它的所有子节点,再换到另外一个结点遍历其所有的子节点。这样一层层遍历,以此类推。
一些模板(常用邻接矩阵存储):
// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点
int h[N], e[N], ne[N], idx;
// 添加一条边a->b
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
// 初始化
idx = 0;
memset(h, -1, sizeof h);
-
深度优先遍历:
int dfs(int u)
{
st[u] = true; // st[u] 表示点u已经被遍历过
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if (!st[j]) dfs(j);
}
}
- 宽度优先遍历:
queue<int> q;
st[1] = true; // 表示1号点已经被遍历过
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; // 表示点j已经被遍历过
q.push(j);
}
}
}
最后奉上代码部分:
#include <bits/stdc++.h>
using namespace std;
#define _for(i, a, b) for (int i = (a); i < (b); i++)
#define _rep(i, a, b) for (int i = (a); i <= (b); i++)
typedef long long ll;
const int N = 100010;
vector<int>edge[N];
bool vis[N];
int n, m;
// 深度优先搜索
void dfs(int u) {//u指当前所在的节点
vis[u] = true;//标记以避免重复访问
cout << u << ' ';//输出
for (int i = 0; i<edge[u].size(); i ++) {
int j = edge[u][i];
if (!vis[j]) dfs(j);//递归到下一层
}
}
// 广度优先搜索
void bfs(int u) {
queue<int> q;
vis[u] = true;
q.push(u);
while (!q.empty()) {
int t = q.front();
cout << t << ' ';
q.pop();//记得要弹出,否则会一直在第一层遍历
for (int i = 0; i<edge[t].size(); i ++) {
int j = edge[t][i];
if (!vis[j]) {
vis[j] = true;
q.push(j);
}
}
}
}
int read() { // 快读函数
int k = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
k = k * 10 + ch - '0';
ch = getchar();
}
return k * f;
}
int main() {
// 读取 n 和 m
n = read(), m = read();
// 读取 m 条边
while (m--)
{
int x, y;
x = read(), y = read();
edge[x].push_back(y);
}
for(int i=1; i<=n; i++) sort(edge[i].begin(),edge[i].end());//排序
dfs(1);
cout<<endl;
memset(vis, false, sizeof(vis));//记得一定要清空
bfs(1);
return 0;
}