比较模板的topological-sort题,关键在于每个元素都严格存在唯一的大小关系,而一般的拓扑排序只给出一个可能解,这就需要每趟排序的过程中监视它是不是总坚持一条唯一的路径。
算法导论里面的拓扑排序运用的是DFS the DAG,记录每个顶点的进入时间和离开时间,根据其先后插入单链表的做法。而我认为一种方法是更直观的,就是维护一个入度为0的顶点集合(我用的队列其实没差),每次对其中一个加入结果序列——同时删除它的所有出边——更新其他点的入度的做法,在我的算法数据结构实现模板里有正确实现https://github.com/jily16/ACMCodes(打广告
在判断拓扑排序结果唯一性时这种方法也表现出了一个优势,每次访问0入度集合时查看大小,当元素多于1的时候可行的选择就出现了分歧——即可判定此DAG的拓扑排序不唯一(当然本题的信息在不断更新,所以不能立刻判死)。
AC代码:
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
//POJ1094
int const INF = 0x3f3f3f3f;
//返回空数组说明暂时不行
//cyclic说明矛盾
vector<int> ts(vector<vector<int> > const &g, bool &cyclic)
{
int n = g.size();
vector<int> d(n);
for (int i = ; i < n; ++i)
{
for (int j = ; j < n; ++j)
{
if (g[i][j] < INF)
{
++d[j];
}
}
}
queue<int> q;
for (int i = ; i < n; ++i) if (d[i] == ) q.push(i);
int d0;
int tot = ;
bool not_unique = false;
vector<int> ans;
while (!q.empty())
{
if (q.size() > )
{
not_unique = true; //解不唯一
}
d0 = q.front();
q.pop();
ans.push_back(d0);
++tot;
for (int i = ; i < n; ++i)
{
if (d[i] != && g[d0][i] < INF)
{
--d[i];
if (d[i] == )
{
q.push(i);
}
}
}
}
if (tot != n) cyclic = true;
if (not_unique) return vector<int>();
else return ans;
}
int main()
{
int n, m;
while (cin >> n >> m && n && m)
{
bool done = false;
vector<vector<int> > g;
char alp1, alp2;
char lessthan;
int num1, num2;
for (int i = ; i < m; ++i)
{
cin >> alp1 >> lessthan >> alp2;
if (done) continue;
num1 = alp1 - 'A';
num2 = alp2 - 'A';
int bignum = max(num1, num2);
//extend the graph
if (g.size() < bignum + )
{
int ori_size = g.size();
for (int i = ; i < ori_size; ++i)
{
for (int j = ; j < bignum + - ori_size; ++j)
{
g[i].push_back(INF);
}
}
for (int i = ; i < bignum + - ori_size; ++i)
{
g.push_back(vector<int>(bignum + , INF));
}
}
g[num1][num2] = ;
//judge from here
bool cycle = false;
if (g.size() < n)
{
ts(g, cycle);
if (cycle)
{
cout << "Inconsistency found after " << i + << " relations.\n";
done = true;
}
else
{
if (i == m - )
{
cout << "Sorted sequence cannot be determined.\n";
done = true;
}
}
}
else
{
vector<int> ans = ts(g, cycle);
if (cycle)
{
cout << "Inconsistency found after " << i + << " relations.\n";
done = true;
}
else
{
if (ans.size() != )
{
cout << "Sorted sequence determined after " << i + << " relations: ";
for (int i = ; i < n; ++i) cout << (char)(ans[i] + 'A');
cout << ".\n";
done = true;
}
else
{
if (i < m - ) continue;
else
{
cout << "Sorted sequence cannot be determined.\n";
done = true;
}
}
}
}
}
}
return ;
}