Sorting It All Out
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 42611 Accepted: 14902
Description
An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from smallest to largest. For example, the sorted sequence A, B, C, D implies that A < B, B < C and C < D. in this problem, we will give you a set of relations of the form A < B and ask you to determine whether a sorted order has been specified or not.
Input
Input consists of multiple problem instances. Each instance starts with a line containing two positive integers n and m. the first value indicated the number of objects to sort, where 2 <= n <= 26. The objects to be sorted will be the first n characters of the uppercase alphabet. The second value m indicates the number of relations of the form A < B which will be given in this problem instance. Next will be m lines, each containing one such relation consisting of three characters: an uppercase letter, the character “<” and a second uppercase letter. No letter will be outside the range of the first n letters of the alphabet. Values of n = m = 0 indicate end of input.
Output
For each problem instance, output consists of one line. This line should be one of the following three:
Sorted sequence determined after xxx relations: yyy…y.
Sorted sequence cannot be determined.
Inconsistency found after xxx relations.
where xxx is the number of relations processed at the time either a sorted sequence is determined or an inconsistency is found, whichever comes first, and yyy…y is the sorted, ascending sequence.
Sample Input
4 6
A<B
A<C
B<C
C<D
B<D
A<B
3 2
A<B
B<A
26 1
A<Z
0 0
Sample Output
Sorted sequence determined after 4 relations: ABCD.
Inconsistency found after 2 relations.
Sorted sequence cannot be determined.
描述:
先给出n个结点(字母A-Z),m条有向边,然后判断图是否存在拓扑偏序。
如果不存在(存在环),则需要输出最早出现的位置。
如果存在多个拓扑序列,则需要输出不确定。
如果存在拓扑序列,则需要输出最早出现的位置。
解题思路:
拓扑排序,每次找到入度为0的点,然后寻边将弧尾的点的入度-1。
通过邻接矩阵mat来记录有向边关系。
因为每次输入一条边,需要根据当前图的状态,判断拓扑排序结果,所以需要每次读入一条边后,进行一次拓扑排序。
注意:
- 可能有重复的输入,eg.例1输入两次"A<B",所以在读入边时,需要根据mat[][] ?= 1来记录入度。
- “where xxx is the number of relations processed at the time either a sorted sequence is determined or an inconsistency is found, whichever comes first”
当出现冲突/拓扑排序时,哪个先出现,先输出结果
在解决问题时,没有看清楚第2个条件,导致我的判定结果都是对最终结果进行评判,即使前面存在拓扑序列,但是最后如果有冲突,那么输出的是INCONSISTENT状态。
已经思考了那么久,就把我用这种思路解题的过程PO一下
- 在找不到拓扑排序时,需要设置一个标志位flag,来标记出现冲突,在之后的读入过程中,可以跳过拓扑排序操作。
- 在未知最后是否能得到拓扑序列时,如果当前能找到拓扑序列,需要及时记录位置index,并且在不产生冲突的情况下,用标志位flag锁死index。
//flag的状态设置为宏变量
int flag = -1;
for(;;)
{
...
if(flag != CONFLICTED)
{
flag = toposort();
if(flag == CONFLICTED)
index = i + 1;
else if(flag == DETER && index == 0)
index = i + 1;
}
else if(flag == CONFLICTED)
continue;
}
在进行TopoSort的过程中,由于一个点想错了,调试了很久,这里也把我的错误思路PO出来以供参考:
int TopoSort()
{
...
else if(zero > 1)
{
return UNDETER;
}
...
}
一旦找到的零点不止一个,那么就判定,当前拓扑排序的输出结果为UNDETER。
这是错误的:
想象一个极端的情况,总共有无穷个点,其中三个点成环,但是入度为零的点不止一个,怎么能够判定当前的状态是存在一个拓扑序列呢?
参考了一下别人的代码
POJ 1094 Sorting It All Out(拓扑排序)解题报告
结合自己的部分
#include <stdio.h>
#include <string.h>
#include <iostream>
#define DETER 1
#define CONFLICTED 2
#define UNDETER 3
using namespace std;
int mat[27][27];
int in[27];
bool sorted[27];
char output[27];
int n,m;
int toposort() {
int cnt = 0;
bool legal;
int flag = CONFLICTED;
int iin[30];
// 复制一份入度数组,防止影响原数组
memcpy(iin, in, sizeof(in));
for(int i=0; i<n; ++i) {
//是否存在入度为0的结点
legal = false;
int zero = 0;
// 统计当前入度为0的点的个数
for(int j=0; j<n; ++j) {
if(iin[j] == 0)
zero++;
}
// 如果入度为0的点的个数大于1,标记为未确定
if(zero > 1) flag = UNDETER;
for(int j=0; j<n; ++j) {
if(iin[j] == 0) {
output[n-i-1] = j + 'A';
iin[j]--;
for(int k=0; k<n; ++k) {
if(mat[k][j])
iin[k]--;
}
legal = true;
break;
}
}
if(!legal) break;
}
if(!legal) return CONFLICTED;
else if(legal && flag==UNDETER)
return UNDETER;
else return DETER;
}
int main()
{
while(scanf("%d %d", &n, &m), n|m)
{
memset(mat, 0, sizeof mat);
memset(in, 0, sizeof in);
bool conflicted = false;
int index = 0;
char str[10];
int iix,oix;
int confi_NO = 0;
int flag = UNDETER;
bool not_deter = false;
bool jump = false;
for(int i = 0; i < m; ++i)
{
scanf("%s", str);
//没确定就继续
if(flag != UNDETER)
continue;
iix = str[0]-'A';
oix = str[2]-'A';
// 边的方向 row <- col
if(mat[iix][oix] == 0)
{
mat[iix][oix] = 1;
++in[iix];
}
//如果出现冲突,那么要找到最先冲突位置
//如果存在拓扑排序,那么要找到刚开始满足条件的位置
flag = toposort();
index = i + 1;
}
if(flag == DETER)
{
output[n] = '\0';
printf("Sorted sequence determined after %d relations: %s.\n", index, output);
}
else if(flag == CONFLICTED)
printf("Inconsistency found after %d relations.\n", index);
else if(flag == UNDETER)
printf("Sorted sequence cannot be determined.\n");
}
return 0;
}