对于N个大写字母,给定它们的一些偏序关系,要求判断出经过多少个偏序关系之后可以确定它们的排序或者存在冲突,或者所有的偏序关系用上之后依旧无法确定唯一的排序。
利用拓扑排序即可解决这个问题,但由于题目要求的是经过多少个关系之后就可以确定答案,因此每读入一个关系,就要进行一次拓扑排序,如果某一次拓扑排序之后可以确定它们的唯一排序或者发现冲突存在,则后面的直接略过。若读入所有关系之后依然无法确定唯一关系,同时也没有冲突,则输出不能确定唯一排序。若拓扑排序的过程中每次仅有一个点入度为0,则该排序是可以确定的排序,否则若多个点入度为0,则不知道哪个点先哪个点后。若拓扑排序进行到某一步之后无法再继续,则说明存在回路,此时说明存在冲突。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
struct Edge
{
int pos;
int next;
}edge[405];
int cur;
int neigh[26];
int n, m;
int indegree[26];
int queue[28], front, rear;
int seq[26];
int toposort()
{
int indeg[26];
bool res = false;
front = rear = 0;
for (int i = 0; i < n; ++i)
{
indeg[i] = indegree[i];
if (indeg[i] == 0) queue[rear++] = i;
}
int k = 0;
while (front != rear)
{
if (front + 1 < rear) res = true;
int tmp = queue[front++];
seq[k++] = tmp;
int e = neigh[tmp];
while (e != -1)
{
--indeg[edge[e].pos];
if (indeg[edge[e].pos] == 0) queue[rear++] = edge[e].pos;
e = edge[e].next;
}
}
if (k < n) return -1;
if (res) return 0;
return 1;
}
int main()
{
char str[5];
int beg, end;
int err, ans;
while (scanf("%d%d", &n, &m) != EOF)
{
if (!n && !m) break;
for (int i = 0; i < n; ++i)
{
indegree[i] = 0;
neigh[i] = -1;
}
cur = 0;
err = ans = -1;
for (int i = 0; i < m; ++i)
{
scanf("%s", str);
if (err != -1 || ans != -1) continue;
beg = str[0] - 'A';
end = str[2] - 'A';
edge[cur].pos = end;
edge[cur].next = neigh[beg];
neigh[beg] = cur;
++cur;
++indegree[end];
int res = toposort();
if (res == 1) ans = i + 1;
else if (res == -1) err = i + 1;
}
if (ans != -1)
{
printf("Sorted sequence determined after %d relations: ", ans);
for (int i = 0; i < n; ++i) putchar('A' + seq[i]);
printf(".\n");
}
else if (err != -1)
{
printf("Inconsistency found after %d relations.\n", err);
}
else
{
printf("Sorted sequence cannot be determined.\n");
}
}
return 0;
}