POJ1094——拓扑排序和它的唯一性

比较模板的topological-sort题,关键在于每个元素都严格存在唯一的大小关系,而一般的拓扑排序只给出一个可能解,这就需要每趟排序的过程中监视它是不是总坚持一条唯一的路径。

算法导论里面的拓扑排序运用的是DFS the DAG,记录每个顶点的进入时间和离开时间,根据其先后插入单链表的做法。而我认为一种方法是更直观的,就是维护一个入度为0的顶点集合(我用的队列其实没差),每次对其中一个加入结果序列——同时删除它的所有出边——更新其他点的入度的做法,在我的算法数据结构实现模板里有正确实现https://github.com/jily16/ACMCodes(打广告

在判断拓扑排序结果唯一性时这种方法也表现出了一个优势,每次访问0入度集合时查看大小,当元素多于1的时候可行的选择就出现了分歧——即可判定此DAG的拓扑排序不唯一(当然本题的信息在不断更新,所以不能立刻判死)。

AC代码:

  1 #include <vector>
  2 #include <iostream>
  3 #include <queue>
  4 using namespace std;
  5 //POJ1094
  6 int const INF = 0x3f3f3f3f;
  7 //返回空数组说明暂时不行
  8 //cyclic说明矛盾
  9 vector<int> ts(vector<vector<int> > const &g, bool &cyclic)
 10 {
 11     int n = g.size();
 12     vector<int> d(n);
 13     for (int i = 0; i < n; ++i)
 14     {
 15         for (int j = 0; j < n; ++j)
 16         {
 17             if (g[i][j] < INF)
 18             {
 19                 ++d[j];
 20             }
 21         }
 22     }
 23     queue<int> q;
 24     for (int i = 0; i < n; ++i) if (d[i] == 0) q.push(i);
 25     int d0;
 26     int tot = 0;
 27     bool not_unique = false;
 28     vector<int> ans;
 29     while (!q.empty())
 30     {
 31         if (q.size() > 1)
 32         {
 33             not_unique = true;    //解不唯一
 34         }
 35         d0 = q.front();
 36         q.pop();
 37         ans.push_back(d0);
 38         ++tot;
 39         for (int i = 0; i < n; ++i)
 40         {
 41             if (d[i] != 0 && g[d0][i] < INF)
 42             {
 43                 --d[i];
 44                 if (d[i] == 0)
 45                 {
 46                     q.push(i);
 47                 }
 48             }
 49         }
 50     }
 51     if (tot != n) cyclic = true;
 52     if (not_unique) return vector<int>();
 53     else return ans;
 54 }
 55 int main()
 56 {
 57     int n, m;
 58     while (cin >> n >> m && n && m)
 59     {
 60         bool done = false;
 61         vector<vector<int> > g;
 62         char alp1, alp2;
 63         char lessthan;
 64         int num1, num2;
 65         for (int i = 0; i < m; ++i)
 66         {
 67             cin >> alp1 >> lessthan >> alp2;
 68             if (done) continue;
 69             num1 = alp1 - 'A';
 70             num2 = alp2 - 'A';
 71             int bignum = max(num1, num2);
 72             //extend the graph
 73             if (g.size() < bignum + 1)
 74             {
 75                 int ori_size = g.size();
 76                 for (int i = 0; i < ori_size; ++i)
 77                 {
 78                     for (int j = 0; j < bignum + 1 - ori_size; ++j)
 79                     {
 80                         g[i].push_back(INF);
 81                     }
 82                 }
 83                 for (int i = 0; i < bignum + 1 - ori_size; ++i)
 84                 {
 85                     g.push_back(vector<int>(bignum + 1, INF));
 86                 }
 87             }
 88             g[num1][num2] = 1;
 89             //judge from here
 90             bool cycle = false;
 91             if (g.size() < n)
 92             {
 93                 ts(g, cycle);
 94                 if (cycle)
 95                 {
 96                     cout << "Inconsistency found after " << i + 1 << " relations.\n";
 97                     done = true;
 98                 }
 99                 else
100                 {
101                     if (i == m - 1)
102                     {
103                         cout << "Sorted sequence cannot be determined.\n";
104                         done = true;
105                     }
106                 }
107             }
108             else
109             {
110                 vector<int> ans = ts(g, cycle);
111                 if (cycle)
112                 {
113                     cout << "Inconsistency found after " << i + 1 << " relations.\n";
114                     done = true;
115                 }
116                 else
117                 {
118                     if (ans.size() != 0)
119                     {
120                             cout << "Sorted sequence determined after " << i + 1 << " relations: ";
121                             for (int i = 0; i < n; ++i) cout << (char)(ans[i] + 'A');
122                             cout << ".\n";
123                             done = true;
124                     }
125                     else
126                     {
127                         if (i < m - 1) continue;
128                         else
129                         {
130                             cout << "Sorted sequence cannot be determined.\n";
131                             done = true;
132                         }
133                     }
134                 }
135             }
136         }
137     }
138     return 0;
139 }

 

posted @ 2017-03-04 10:40  jily16  阅读(4033)  评论(0编辑  收藏  举报