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


    题目链接:P5318 【深基18.例3】查找文献

    补:输入格式

    第一行两个整数 (n, m)

    接下来 (m) 行,每行两个整数 (X, Y),表示文章 (X) 有参考文献 (Y)

    (其实这题的 (n) 并没有什么卵用……)

    补:输出格式

    (2) 行,每行(n) 个整数,表示遍历的顺序。

    审题&解法

    这题就是给一张图,让你求对它进行深度优先搜索(DFS)和广度优先搜索的(BFS)遍历的顺序。当然是用邻接表来存图。

    这题的难点(我认为的难点)在于这:

    如果有很多篇文章可以参阅,请先看编号较小的那篇

    我们必须先看编号小的,否则输出结果就不能正确。

    尽管题目的样例是排好了序的,但是题目描述中并没有保证输入的数据一定是有序的,而且因为邻接表最后加的边会最先访问,最早加的边会最后访问,我们需要以head[]数组为第一关键字从小到大排序,以to[]数组为第二关键字从大到小排序。

    使用结构体和sort(),再借助cmp()就可以完成排序。

    排序的cmp()函数如下:

    bool cmp(node a, node b) {
      if (a.from == b.from) return a.to > b.to;
      return a.from < b.from;
    }
    

    如果没看懂就好好理解一下。

    代码

    #include <cstdio>
    #include <iostream>
    #include <queue>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    struct node {
      int from, to, nxt;
    }a[1000006];
    
    int head[100005], d[100005];
    bool vis[100005];
    int tot;
    
    bool cmp(node a, node b) {
      if (a.from == b.from) return a.to > b.to; //如果两个的from[]相等,就按to从大到小排序
      return a.from < b.from;                   //否则按from从小到大排序
    }
    
    inline void add(int x, int y) {
      a[++tot].to = y;
      a[tot].nxt = head[x], head[x] = tot;
    }
    
    inline int read() {
      int X = 0; bool flag = 1; char ch = getchar();
      while (ch < '0' || ch > '9') {if (ch == '-') flag = 0; ch = getchar();}
      while (ch >= '0' && ch <= '9') {X = (X << 1) + (X << 3) + ch - '0'; ch = getchar();}
      if (flag) return X;
      return ~ (X - 1);
    }
    
    inline void write(int X) {
      if (X < 0) {putchar('-'); X = ~ (X - 1);}
      int s[50], top = 0;
      while (X) {s[++top] = X % 10; X /= 10;}
      if (!top) s[++top] = 0;
      while (top) putchar(s[top--] + '0');
      putchar(' ');
      return;
    }
    
    void dfs(int x) {
      write(x);
      vis[x] = true;   //标记到过
      for (int i = head[x]; i; i = a[i].nxt) { //循环出边
        if (!vis[a[i].to])  //如果没到过
          dfs(a[i].to);     //就搜索它
      }
      return;
    }
    
    void bfs() {      //广搜
      queue<int> que; //先定义一个队列
      que.push(1); d[1] = 1;            //将1加入队列
      while (!que.empty()) {            //循环,直到队列为空
        int x = que.front(); que.pop(); //从队头取出一个值,把它弹出
        write(x);                       //把它输出
        for (int i = head[x]; i; i = a[i].nxt) { //循环他的每一条出边,如果没有访问过,就把它加入队列
          int y = a[i].to;
          if (d[y]) continue;
          d[a[i].to] = 1;               //标记它被访问过(本来存深度,但在这题它退化了),本来应该为d[y] = d[x] + 1;
          que.push(y);                  //将加入队列
        }
      }
    }
    
    signed main() {
      int m;
      m = read(); m = read();
      for (int i = 1; i <= m; i++) {          //先在结构体里输入,但不加边
        a[i].from = read(); a[i].to = read(); 
      }
      sort(a + 1, a + m + 1, cmp);            //输入完之后排序
      for (int i = 1; i <= m; i++) {          //排完序之后加边,
        add(a[i].from, a[i].to);              //这样可以保证先搜索到的一定是编号最小的
      }
      dfs(1);                                 //从1开始深搜
      putchar('
    ');                          //输出完深搜的就换行
      bfs();                                  //广搜
      putchar('
    ');
      return 0;
    }
  • 相关阅读:
    C++ Call C# COM
    C ++ / CLI 语法
    C#调用C++ DLL动态库的两种方式
    Linux下的JMeter部署及使用
    同时处理多请求(带超时时间)
    同时处理多请求
    curl命令
    mysql命令
    SpringBoot配置文件敏感信息加密-jasypt
    spring boot升级到2.x的坑
  • 原文地址:https://www.cnblogs.com/g-mph/p/14636448.html
Copyright © 2020-2023  润新知