zoukankan      html  css  js  c++  java
  • 拓扑排序

    拓扑排序

    从离散数学的角度定义,假设(A,≤)是有限偏序集,对其进行拓扑排序是指将其扩展成一个全序集,使得≤∈<,即对任意的a,b∈A,若a≤b,则a<b。

    从图论的角度定义,对一个有向无环图G进行拓扑排序,是将G中所有的顶点排成一个线性序列,使得图中任意一对顶点u和v,如果(u,v)∈E(G),则u在线性序列中应出现在v之前。

    思路

    从离散数学的角度定义,拓扑排序是针对有限偏序集的,由离散数学的知识知,若(A,≤)是偏序集,则拟序集(A,<)中不存在长度大于1的环(这其实与无环图对应),所以有限偏序集可以画成哈斯(Hasse)图。Hasse图非空时总存在极小元,每次输出极小元,更新Hasse图,直到Hasse为空。

    从图论的角度,极小元等同于图中入度为0的顶点,每次输出入度为0的点,更新与之相连点的入度,直到输出全部顶点。如果存在顶点没有输出,说明存在环。

    样题

    给任务排序(UVa10305)

    假设有n个任务,还有m个二元组(u,v),(u,v)表示u必须在v之前执行。请输出n个任务按顺序执行的一种可能情况。

    代码实现

    邻接矩阵+队列

     1 #include<stdio.h>
     2 #include<cstring>
     3 #include<queue>
     4 #include<vector>
     5 using namespace std;
     6 
     7 const int V = 100 + 10;            //最大顶点数
     8 const int E = 100 * 100 + 10;    //最大边数
     9 vector<int>e[V];        //邻接矩阵存图
    10 int in[V];                //顶点的入度
    11 
    12 int m, n;
    13 
    14 int main()
    15 {
    16     while (scanf("%d%d", &n, &m) == 2 && n)
    17     {
    18         for (int i = 0; i < n; i++)        
    19         {
    20             e[i].clear();
    21             in[i] = 0;
    22         }
    23         for (int i = 0; i < m; i++)
    24         {
    25             int from, to;
    26             scanf("%d%d", &from, &to);
    27             e[from].push_back(to);
    28             in[to]++;
    29         }
    30         vector<int>ans;
    31         queue<int>q;
    32         for (int i = 1; i <= n; i++)  if (!in[i])    q.push(i); //将入度为0的入队
    33         while (!q.empty())
    34         {
    35             int u = q.front(); q.pop();
    36             ans.push_back(u);
    37             for (int i = 0; i < e[u].size(); i++)        //遍历与之相连的顶点
    38                 if ((--in[e[u][i]]) == 0)  q.push(e[u][i]);    //入度减1,如果为0,入队
    39         }
    40         for (int i = 0; i < ans.size(); i++)
    41             printf("%d ", ans[i]);
    42         printf("
    ");
    43     }
    44     return 0;
    45 }

     dfs

     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<vector>
     6 #include<cstring>
     7 using namespace std;
     8 
     9 const int maxn = 100 + 10;
    10 vector<int>G[maxn];
    11 int c[maxn], topo[maxn], t;
    12 int n, m;
    13 
    14 bool dfs(int u)
    15 {
    16     c[u] = -1;    //正在访问,dfs(u)正在栈帧中,尚未返回
    17     for (int i = 0; i < G[u].size(); i++)
    18     {
    19         if (G[u][i])
    20         {
    21             if (c[G[u][i]] < 0) return false;
    22             else if (!c[G[u][i]] && !dfs(G[u][i]))    return false;
    23         }
    24     }
    25     c[u] = 1;    //已经访问过,dfs(u)已被调用过,并已访问
    26     topo[--t] = u;
    27     return true;
    28 }
    29 
    30 bool toposort()
    31 {
    32     t = n;
    33     memset(c, 0, sizeof(c));
    34     for (int i = 1; i <= n; i++)
    35         if (!c[i] && !dfs(i))        //c[i]为0表示从未访问过
    36             return false;
    37     return true;
    38 }
    39 
    40 void slove()
    41 {
    42     if (toposort())
    43     {
    44         for (int i = n - 1; i >= 0; i--)
    45             printf("%d ", topo[i]);
    46         printf("
    ");
    47     }
    48 }
    49 
    50 int main()
    51 {
    52     int u, v;
    53     while (scanf("%d%d", &n, &m) == 2 && n)
    54     {
    55         for (int i = 0; i <= n; i++)    G[i].clear();
    56         for (int i = 0; i < m; i++)
    57         {
    58             scanf("%d%d", &u, &v);
    59             G[v].push_back(u);
    60         }
    61         slove();
    62     }
    63     return 0;
    64 }

     参考链接:

    https://baike.baidu.com/item/拓扑排序/5223807?fr=aladdin

    https://blog.csdn.net/qq_41713256/article/details/80805338

    中国大学mooc  刘铎  离散数学

  • 相关阅读:
    。。。。。。
    数据库
    python基础
    。。。。
    drf
    CRM笔记梳理
    人生苦短,我学PYTHON
    React的初步了解
    递归与迭代比较
    有没有大佬会很标准的三层架构
  • 原文地址:https://www.cnblogs.com/lfri/p/9897165.html
Copyright © 2011-2022 走看看