这道题有隐含这一信息,每输入一对关系,如果判定有结果,则可以忽略后面输入数据,即使后面输入数据能改变结果,也不用管。所以应该每输入一个关系就去更新当前的图,然后进行一趟拓扑排序。一旦产生结果,再对后面的数据处理下,就可以输出结果。
所有可能的情况罗列:
(独家经验原创,重中之重!可以说没有这些,这题就无法AC!)
一、当输入的字母全部都在前n个大写字母范围内时:
(1) 最终的图 可以排序:
在输入结束前如果能得到最终的图(就是用这n个字母作为顶点,一个都不能少);
而且最终得到的图 无环;
只有唯一一个 无前驱(即入度为0)的结点,但允许其子图有多个无前驱的结点。
在这步输出排序后,不再对后续输入进行操作
(2)输出矛盾
在输入结束前如果最终图的子图有环
在这步输出矛盾后,不再对后续输入进行操作
(3)输出无法确认排序
这种情况必须全部关系输入后才能确定,其中又有2种可能
①最终图的字母一个不缺,但是有多个 无前驱结点
②输入结束了,但最终的图仍然字母不全,与 无前驱结点 的多少无关
二、当输入的字母含有 非前n个大写字母 的字母时(超出界限):
(1) 输出矛盾
输入过程中检查输入的字母(结点),若 前n个大写字母 全部出现,则在最后一个大写字母出现的那一步 输出矛盾
(2) 输出无法确认排序
最后一步输入后,前n个大写字母 仍然未全部出现,则输出 无法确认排序
PS:在使用“无前驱结点”算法时必须要注意,在“矛盾优先”的规律下,必须考虑一种特殊情况,就是多个无前驱结点与环共存时的情况,即输入过程中子图都是有 多个无前驱结点,最后一步输入后出现了环,根据算法的特征,很容易输出“不能确认排序”,这是错的,必须适当修改算法,输出“矛盾”。
例如:
6 6
A<F
B<D
C<E
F<D
D<E
E<F
输出矛盾
//Memory Time //276K 0MS #include<iostream> using namespace std; int n,m; //n结点下限,m关系对 char top_out[26]; //排序输出列表 int po=0; //输出列表的指针 typedef class degree { public: int in; //入度 char to[26]; //记录指向的所有顶点,以便删除出度的操作 int pt; //数组to的指针 }; int top_sort(degree alph[],bool mark[],int num) { /*假设图G的当前子图为F*/ memset(top_out,'