AcWing 848. 有向图的拓扑序列

AcWing 848. 有向图的拓扑序列

用BFS来写拓扑,以前还真没想过这个思路
之前用的都是深搜找拓扑序

依然是正常用数组实现一个邻接表,然后用数组模拟队列,从入度为0,即d[i] == 0的点开始搜索
用数组模拟队列的原因是为了最后方便直接输出拓扑序,就不用另开一个数组专门存储了

代码中的几个小细节:

  1. 把邻接表的头指针初始化为-1, memset(h, -1, sizeof h);,来表示邻接表为空,不然会死循环导致TLE
  2. 往队列中添加元素的操作是q[++tt] = i;,弹出元素则是hh++;或者t = q[hh++];,和这几个操作配套的一个细节是要把队尾初始为-1,int hh = 0, tt = -1;

示例代码里有很多short cut, 感觉不熟练容易写歪来= =, 比如我老是忘记初始化h[]数组,然后写完要补上一行 QwQ

代码实现
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int h[N], e[N], ne[N], idx;
int q[N], d[N];
int n, m;

void add(int a, int b){
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

bool toposort(){
    int hh = 0, tt = -1;

    for(int i = 1; i <= n; i++)
        if(!d[i])
            q[++ tt] = i;

    while(hh <= tt){
        int t = q[hh ++];

        for(int i = h[t]; i != -1; i = ne[i]){
            int j = e[i];
            if(--d[j] == 0)
                q[++tt] = j;
        }
    }

    return tt == n - 1;
}

int main(){
    scanf("%d%d", &n, &m);

    memset(h, -1, sizeof h);

    for(int i = 0; i < m; i++){
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b);

        d[b] ++ ;
    }

    if(!toposort()) puts("-1");
    else{
        for(int i = 0; i < n; i++) printf("%d ", q[i]);
        puts("");
    }

    return 0;
}
上一篇:显示器桌面方向的问题


下一篇:Spring Boot日志打印