zoukankan      html  css  js  c++  java
  • 拓扑排序(基于dfs+基于队列)

    经典问题-Ordering Tasks

    dfs函数的返回值表示是否成环,若存在有向环,则不存在拓扑排序。不包含有向环的有向图称为有向无环图(DAG)

    可以借助DFS完成拓扑排序,在访问完一个结点时把他加入当前拓扑序的首部。

    举个栗子:比如一个(1,2),(1,3),(2,3)的有向无环图,就先搜索1,再递归搜索2,再搜索3,3没有出度了,于是放进拓扑序尾=,再回到2,2除3外没有出度,再放入拓扑序,再回到1,1除2,3没有出度,放入拓扑序

     1 #include <algorithm>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <iostream>
     6 #include <cstdlib>
     7 #include <set>
     8 #include <vector>
     9 #include <cctype>
    10 #include <iomanip>
    11 #include <sstream>
    12 #include <climits>
    13 #include <queue>
    14 #include <stack>
    15 using namespace std;
    16 typedef long long ll;
    17 #define INF 0X3f3f3f3f
    18 const ll MAXN = 1e3 + 7;
    19 const ll MOD = 1e9 + 7;
    20 int mp[MAXN][MAXN];
    21 int vis[MAXN];
    22 int topo[MAXN], t;//topo数组存放最后拓扑排序结果
    23 int n,k,m;
    24 bool dfs(int u)//判环
    25 {
    26     vis[u] = -1; //访问标志
    27     for(int i=1;i<=n;i++)
    28     {
    29         if(mp[u][i])
    30         {
    31             if(vis[i]==-1) return false;//存在有向环,退出
    32             if(!vis[i]&&!dfs(i)) return false;
    33         }
    34     }
    35     topo[--k]=u;
    36     vis[u]=1;
    37     return true;
    38 }
    39 bool toposort()
    40 {
    41     memset(vis,0,sizeof(vis));
    42     k=n;
    43     for(int i=1;i<=n;i++)
    44          if(!vis[i]&&!dfs(i)) return false;
    45     return true;
    46 }
    47 void print()
    48 {
    49     for(int i=0;i<n;i++)
    50     {
    51         if(i) cout<<' ';
    52         cout<<topo[i];
    53     }
    54     cout<<endl;
    55     return ;
    56 }
    57 int main()
    58 {
    59     ios::sync_with_stdio(false);
    60     while (cin >> n >> m&&(n|m))
    61     {
    62         memset(mp,0,sizeof(mp));
    63         for (int i = 0; i < m; i++)
    64         {
    65             int a,b;
    66             cin>>a>>b;
    67             mp[a][b]=1;
    68         }
    69         if(toposort())
    70         print();
    71         else
    72         cout<<"sorry to say there is no DAG"<<endl;//跟题目并没有关系...
    73     }
    74     return 0;
    75 }
    View Code

     加个队列写法..

     1 #include <algorithm>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <iostream>
     6 #include <cstdlib>
     7 #include <set>
     8 #include <vector>
     9 #include <cctype>
    10 #include <iomanip>
    11 #include <sstream>
    12 #include <climits>
    13 #include <queue>
    14 #include <stack>
    15 using namespace std;
    16 typedef long long ll;
    17 #define INF 0X3f3f3f3f
    18 const ll MAXN = 1e3 + 7;
    19 const ll MOD = 1e9 + 7;
    20 int n, m;
    21 int degree[MAXN][MAXN];
    22 int indegree[MAXN];
    23 int topo[MAXN];
    24 void toposort()
    25 {
    26     int cnt = 0;
    27     queue<int> que;
    28     for (int i = 1; i <= n; i++)
    29         if (!indegree[i])
    30             que.push(i);
    31     int cur;
    32     while (!que.empty())
    33     {
    34         cur = que.front();
    35         que.pop();
    36         topo[cnt++] = cur;
    37         for (int i = 1; i <= n; i++)
    38         {
    39             if (degree[cur][i])
    40             {
    41                 indegree[i]--;
    42                 if (!indegree[i])
    43                     que.push(i);
    44             }
    45         }
    46     }
    47     return;
    48 }
    49 void print()
    50 {
    51     for (int i = 0; i < n; i++)
    52     {
    53         if (i)
    54             cout << ' ';
    55         cout << topo[i];
    56     }
    57     cout << endl;
    58     return;
    59 }
    60 int main()
    61 {
    62     ios::sync_with_stdio(false);
    63     while (cin >> n >> m && (n | m))
    64     {
    65         memset(degree, 0, sizeof(degree));
    66         memset(indegree, 0, sizeof(indegree));
    67         while (m--)
    68         {
    69             int a, b;
    70             cin >> a >> b;
    71             if (!degree[a][b])
    72             {
    73                 degree[a][b] = 1;
    74                 indegree[b]++;
    75             }//处理重边
    76         }
    77         toposort();
    78         print();
    79     }
    80     return 0;
    81 }
    View Code
  • 相关阅读:
    P4097 [HEOI2013]Segment 李超线段树
    P3592 [POI2015]MYJ
    P3698 [CQOI2017]小Q的棋盘
    P4098 [HEOI2013]ALO 可持久化01Trie
    P2331 [SCOI2005]最大子矩阵
    P4099 [HEOI2013]SAO
    loj #6032. 「雅礼集训 2017 Day2」水箱 线段树优化DP转移
    CF765F Souvenirs 离线+线段树+主席树
    CF1097D Makoto and a Blackboard
    loj #6570. 毛毛虫计数
  • 原文地址:https://www.cnblogs.com/graytido/p/10419230.html
Copyright © 2011-2022 走看看