洛谷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,用通俗的话来说,就是你从图中的一个节点出发,其有几个子节点,你会先将这所有的子节点遍历,再挑其中的一个子节点,遍历它的所有子节点,再换到另外一个结点遍历其所有的子节点。这样一层层遍历,以此类推。

一些模板(常用邻接矩阵存储):

cpp 复制代码
// 对于每个点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);
深度优先遍历:
cpp 复制代码
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);
    }
}
  • 宽度优先遍历:
cpp 复制代码
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);
        }
    }
}

最后奉上代码部分:

cpp 复制代码
#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;
}
相关推荐
计算机小白一个6 小时前
蓝桥杯 Java B 组之设计 LRU 缓存
java·算法·蓝桥杯
万事可爱^6 小时前
HDBSCAN:密度自适应的层次聚类算法解析与实践
算法·机器学习·数据挖掘·聚类·hdbscan
大数据追光猿8 小时前
Python应用算法之贪心算法理解和实践
大数据·开发语言·人工智能·python·深度学习·算法·贪心算法
Dream it possible!8 小时前
LeetCode 热题 100_在排序数组中查找元素的第一个和最后一个位置(65_34_中等_C++)(二分查找)(一次二分查找+挨个搜索;两次二分查找)
c++·算法·leetcode
夏末秋也凉8 小时前
力扣-回溯-46 全排列
数据结构·算法·leetcode
南宫生8 小时前
力扣每日一题【算法学习day.132】
java·学习·算法·leetcode
柠石榴8 小时前
【练习】【回溯No.1】力扣 77. 组合
c++·算法·leetcode·回溯
Leuanghing8 小时前
【Leetcode】11. 盛最多水的容器
python·算法·leetcode
qy发大财8 小时前
加油站(力扣134)
算法·leetcode·职场和发展
王老师青少年编程8 小时前
【GESP C++八级考试考点详细解读】
数据结构·c++·算法·gesp·csp·信奥赛