P5318 【深基18.例3】查找文献

 展开

题目描述

小K 喜欢翻看洛谷博客获取知识。每篇文章可能会有若干个(也有可能没有)参考文献的链接指向别的博客文章。小K 求知欲旺盛,如果他看了某篇文章,那么他一定会去看这篇文章的参考文献(如果他之前已经看过这篇参考文献的话就不用再看它了)。

假设洛谷博客里面一共有 n(n\le10^5)n(n≤105) 篇文章(编号为 1 到 nn)以及 m(m\le10^6)m(m≤106) 条参考文献引用关系。目前小 K 已经打开了编号为 1 的一篇文章,请帮助小 K 设计一种方法,使小 K 可以不重复、不遗漏的看完所有他能看到的文章。

这边是已经整理好的参考文献关系图,其中,文献 X → Y 表示文章 X 有参考文献 Y。不保证编号为 1 的文章没有被其他文章引用。(这句话看错了,看成了 保证1没有被其他文章引用)

请对这个图分别进行 DFS 和 BFS,并输出遍历结果。如果有很多篇文章可以参阅,请先看编号较小的那篇(因此你可能需要先排序)。

输入格式

输出格式

输入输出样例

输入 #1复制

8 9
1 2
1 3
1 4
2 5
2 6
3 7
4 7
4 8
7 8

输出 #1复制

1 2 5 6 3 7 8 4 
1 2 3 4 5 6 7 8  

解题类型:bfs, dfs

解题思路:读入, 分别用bfs, dfs输出

注意点:先输出编号偏小的文献,要排序。

                注意出口设置;

错误代码(只过了一个样例):

#include <bits/stdc++.h>
#define MAXN 1e6+2
#define inf 0x3f3f3f3f
#define rep(x, a, b) for(int x=a; x<=b; x++)
#define per(x, a, b) for(int x=a; x>=b; x--)
using namespace std;
const int NC = 1e6+2;
vector<int> group[NC];
bitset<NC> vis;
void dfs(int x)
{
    if(!group[x].size())
    {
        return;
    }
    else
    {
        sort(group[x].begin(), group[x].end());
        rep(i, 0, (int)group[x].size()-1)
        {
            if(!vis[group[x][i]])
            {
                printf("%d ", group[x][i]);
                vis[group[x][i]] = 1;
                dfs(group[x][i]);
            }
        }
    }

}
int main()
{
    vis.reset();
    int n, m;
    scanf("%d%d", &n, &m);
    rep(i, 1, m)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        group[a].push_back(b);
    }
    printf("1 ");
    dfs(1);
    cout<<endl;
    vis.reset();
    /*bfs*/
    queue<int> que;
    que.push(1);
    while(!que.empty())
    {
        int x = que.front();
        que.pop();
        printf("%d ", x);

        sort(group[x].begin(), group[x].end());
        rep(i, 0, (int)group[x].size()-1)
        {
            if(!vis[group[x][i]])
            {
                vis[group[x][i]] = 1;
                que.push(group[x][i]);
            }
        }
    }
    return 0;
}

错误代码的dfs:出口设置不好

错误点:看错了文章1,文章1可能会被其他文章引用,入队和递归,文章1都要标记不然会报错。

优先输出编号小的,且不输出已经输出过的。

修正代码:(AC)

#include <bits/stdc++.h>
#define MAXN 1e6+2
#define inf 0x3f3f3f3f
#define rep(x, a, b) for(int x=a; x<=b; x++)
#define per(x, a, b) for(int x=a; x>=b; x--)
using namespace std;
const int NC = 1e6+2;
vector<int> group[NC];
bitset<NC> vis;
void dfs(int x)
{
    if(!group[x].size())
    {
        return;
    }
    else
    {
        sort(group[x].begin(), group[x].end());
        rep(i, 0, (int)group[x].size()-1)
        {
            if(!vis[group[x][i]])
            {
                printf("%d ", group[x][i]);
                vis[group[x][i]] = 1;
                dfs(group[x][i]);
            }
        }
    }

}
int main()
{
    vis.reset();
    int n, m;
    scanf("%d%d", &n, &m);
    rep(i, 1, m)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        group[a].push_back(b);
    }
    printf("1 ");
    vis[1] = 1; //wrong reason!!!
    dfs(1);
    cout<<endl;
    vis.reset();
    /*bfs*/
    queue<int> que;
    que.push(1);
    vis[1] = 1;//wrong reason!!!
    while(!que.empty())
    {
        int x = que.front();
        que.pop();
        printf("%d ", x);

        sort(group[x].begin(), group[x].end());
        rep(i, 0, (int)group[x].size()-1)
        {
            if(!vis[group[x][i]])
            {
                vis[group[x][i]] = 1;
                que.push(group[x][i]);
            }
        }
    }
    return 0;
}

优化代码:(AC)

1) 全部压入队列,或者进入下一级递归,再判断有无出现过,若出现过则不输出,若无,则输出并继续将该文献的子文献入队和递归,这种方法不用特殊地标记文章1。(这个优化的dfs方便,但bfs代码太长,没有上面的好用,可以拆一下重新组合

#include <bits/stdc++.h>
#define MAXN 1e6+2
#define inf 0x3f3f3f3f
#define rep(x, a, b) for(int x=a; x<=b; x++)
#define per(x, a, b) for(int x=a; x>=b; x--)
using namespace std;
const int NC = 1e6+2;
vector<int> group[NC];
bitset<NC> vis;
void dfs(int x)
{
    if(vis[x])
    {
        return;
    }
    else
    {
        vis[x] = 1;
        printf("%d ", x);
        sort(group[x].begin(), group[x].end());
        rep(i, 0, (int)group[x].size()-1)
        {
            dfs(group[x][i]);
        }
    }

}
int main()
{
    vis.reset();
    int n, m;
    scanf("%d%d", &n, &m);
    rep(i, 1, m)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        group[a].push_back(b);
    }
    dfs(1);
    cout<<endl;
    vis.reset();

    /*bfs*/
    queue<int> que;
    que.push(1);
    while(!que.empty())
    {
        int x = que.front();
        que.pop();
        if(vis[x])
        {
            continue;
        }
        else
        {
            vis[x] = 1;
            printf("%d ", x);
             sort(group[x].begin(), group[x].end());
            rep(i, 0, (int)group[x].size()-1)
            {
                que.push(group[x][i]);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_54674275/article/details/121302431