• AcWing 848. 有向图的拓扑序列


    模拟队列

    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int N = 100010;
    int n, m;
    int h[N], e[N], ne[N], idx;//邻接表
    int d[N];//入度
    int q[N];//队列
    void add(int a, int b) {
        e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
    }
    bool topsort() {
        int hh = 0, tt = -1;
        for (int i = 1; i <= n; i ++ )
            if (!d[i])//先把所有入度为0的点插入到队列
                q[ ++ tt] = i;//进入队列
        while (hh <= tt) {
            int t = q[hh ++ ];//取出进度为0
            for (int i = h[t]; i != -1; i = ne[i]) {//所有和i相连的点,也就是和入度为0的点相连的点
                //入度都要减一
                int j = e[i];  //找到出边
                d[j]--;//让入度减,也就是把出边剪掉
                if (d[j] == 0)//当进度减为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 (!topsort()) puts("-1");
        else {
            for (int i = 0; i < n; i ++ ) printf("%d ", q[i]);
            puts("");
        }
        return 0;
    }

    队列

    #include <bits/stdc++.h>
    using namespace std;
    int const N = 1e5 + 10;
    int e[N], ne[N], h[N], idx, d[N];
    int n, m;
    vector<int> ans;
    // 建立邻接表
    void add(int a, int b) {
        e[idx] = b, ne[idx] = h[a], h[a] = idx++;
    }
    
    // 拓扑排序
    void top_sort() {
        queue<int> q;  // 维护一个队列
        for (int i = 1; i <= n; ++i) if (!d[i]) q.push(i);  // 把入度为0的点加入队列
        // 当队列不为空时
        while (q.size()) {
            auto t = q.front();  // 取队头
            q.pop();  // 队头出队
            ans.push_back(t);  // 把这个数字放入答案序列
            for (int i = h[t]; i != -1; i = ne[i]) { // 枚举所有队头元素相邻的元素
                int j = e[i];
                d[j]--;  // 队头元素出队相当于把与队头元素相连的元素的入度减一
                if (!d[j]) q.push(j);  // 把入度为0的元素放入队列
            }
        }
        if (ans.size() == n) { // 输出答案序列
            for (auto a: ans) printf("%d ", a);
        } else cout << "-1";
    }
    
    int main() {
        cin >> n >> m;  // 输入点数和边数
        memset(h, -1, sizeof h);  // 初始化h
        for (int i = 0; i < m; ++i) { // 读入每条边
            int a, b;
            scanf("%d %d", &a, &b);
            add(a, b);  // 把b插入a的边表
            d[b]++;  // b的入度加一
        }
        top_sort();
        return 0;
    }
  • 相关阅读:
    Openjudge-计算概论(A)-单词翻转
    Openjudge-计算概论(A)-字符串排序
    Openjudge-计算概论(A)-过滤多余的空格
    Openjudge-计算概论(A)-单词倒排
    Openjudge-计算概论(A)-统计字符数
    Openjudge-计算概论(A)-奇数单增序列
    碎碎的光阴(湖北荆门一考生)
    Openjudge-计算概论(A)-找和为K的两个元素
    php延迟加载的示例
    php排序测试
  • 原文地址:https://www.cnblogs.com/QingyuYYYYY/p/11831954.html
Copyright © 2020-2023  润新知