zoukankan      html  css  js  c++  java
  • 【图论】拓扑排序

    算法一:

    寻找入度为0(没有任何结点指向它)的结点Q,删除Q及与Q相连的边。

    重复上述操作直到结点被全部删除,或找不到入度为0的结点(存在有向环,非DAG)。


    算法二:

    遍历每一个结点,通过DFS访问结点的所有子孙。当前结点无子孙时为递归边界,将结点加入到当前拓扑序的首部

    需要注意的是,要判断递归路上是否有遇到存在有向环的结点,故要用(vis[u])存储结点状态:

    (vis[u]=0)时,结点(u)从未访问过;

    (vis[u]=-1)时,结点(u)正在访问;

    (vis[u]=1)时,结点(u)已访问完毕。

    int E[1000 + 10][1000 + 10];
    int vis[100 + 10];
    int topo[100 + 10];
    int n, m, pos;
    bool dfs(int V) {
        vis[V] = -1;
        for (int u = 1;u <= n;u++) {
            if (E[V][u]) {
                if (vis[u] < 0) return false;//存在有向环
                else if (!vis[u] && !dfs(u)) return false;//没访问过的新结点进行访问,但过程中出现有向环
            }
        }
        vis[V] = 1;
        topo[pos] = V;
        pos--;
        return true;
    }
    
    bool toposort() {
        for (int u = 1;u <= n;u++) {
            if (!vis[u] && !dfs(u))return false;
        }
        return true;
    }
    
    int main()
    {
        while (cin >> n >> m) {
            if (!n && !m) break;
            memset(E, 0, sizeof(E));
            memset(topo, 0, sizeof(topo));
            memset(vis, 0, sizeof(vis));
            pos = n;
            for (int i = 1;i <= m;i++) {
                int a, b;
                cin >> a >> b;
                E[a][b] = 1;
            }
            if (toposort()) {
                cout << topo[1];
                for (int i = 2;i <= n;i++) cout << " " << topo[i];
                cout << endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Java实现 LeetCode 69 x的平方根
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 66 加一
    Java实现 LeetCode 66 加一
    CxSkinButton按钮皮肤类
  • 原文地址:https://www.cnblogs.com/streamazure/p/12664250.html
Copyright © 2011-2022 走看看