题目大意:
现有多个测例,每个测例都会给定一个序列长度n(2 ≤ n ≤ 26),序列有大写字母的前n个字母组成,接下来给定m个关系约束,每个关系由小于号规定,形式比如为"A < B",每读一个关系就要判断该序列是否能确定或者是否前后矛盾(比如前面的关系能推出A < B,后面的关系又能推出A > B),如果能确定出序列就要输出经过多少条关系后能确定出此序列,并且打印出该序列,如果推出前后矛盾,也要输出是经过多少条关系推出了前后矛盾这个结论,如果经过所有关系后也不能确定出该序列或者推出前后矛盾,就输出该序列无法确定的信息,输入的关系中的字母保证多处于前n个大写字母的范围,测例以n, m = 0表示结束。
注释代码:
/*
* Problem ID : POJ 1094 Sorting It All Out
* Author : Lirx.t.Una
* Language : C++
* Run Time : 16 ms
* Run Memory : 180 KB
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
//序列最大长度
#define MAXN 26
using namespace std;
char deg[MAXN];//degree,入度
char tmp_deg[MAXN];//临时空间,可以存放deg副本
bool g[MAXN][MAXN];//graph,存放序列中各个元素之间的关系
char fmt[4];//临时接受输入的字符串
queue<char> ord;//存放最终确定下来的序列
int
topsort( int n, char *deg ) {//拓扑排序
//n为序列的长度
//deg,入度信息
int i;//计数变量
int u, v;//点
bool nosure;//标记序列是否是不确定的(就是拓扑排序会产生多种情况)
queue<char> que;//存放入度为0的点
//上次排序可能不成功,有上次的信息留在ord中,需要清空不影响本次排序
while ( !ord.empty() ) ord.pop();
for ( i = 0; i < n; i++ )//找出所有入度为0的点存放到que中
if ( !deg[i] ) que.push(i);
nosure = false;//将不确定标记置为false
while ( !que.empty() ) {
//如果在去0入度点时有多个,就意味着拓扑排序的情况有多种
if ( que.size() > 1 ) nosure = true;//将情况置为不确定
//!!但是不确定并不意味着检查可以结束,因为可能会出现前后矛盾的情况
//随着关系的增多不确定可能会转化为确定,但是一旦发现矛盾的情况就
//应该立即对本次测例给出判断结论了
ord.push((u = que.front()) + 'A');//暂且将该点放入ord中,如果最终不确定不输出就行了
que.pop();
for ( v = 0; v < n; v++ )//将所有与之相连的点的入度都-1,并且如果-1后为0就如队
if ( g[u][v] && !(--deg[v]) )
que.push(v);
}
//如果仍然有部分点入度不为0则表示有环,即出现了前后矛盾的情况
if ( ord.size() < n ) return 'I';//比如A > B > C > A,这就矛盾了,并返回(I)nconsistency标记
if ( nosure ) return 'N';//虽然不矛盾但是不确定(即有多种情况,序列不能唯一确定),返回(N)ot sure标记
return 'D';//序列被唯一确定下来了,返回(D)etermained标记
}
int
main() {
int n, m;//序列长度,关系数
int u, v;//点
int stp;//表示经过多少步得出结论
int i;//计数变量
bool incn, detm;//inconsistency and determained,标记是否矛盾或者被唯一确定
while ( scanf("%d%d", &n, &m), n ) {
//初始化
incn = false;
detm = false;
memset(g, false, sizeof(g));
memset(deg, 0, sizeof(deg));
for ( i = 1; i <= m; i++ ) {
scanf("%s", fmt);
if ( incn || detm ) continue;//如果两者中有一个被确定则不必再检查
//虽然已经判断出来了但是也要把剩余的关系读完
u = fmt[0] - 'A';//映射成数组下标
v = fmt[2] - 'A';
if ( g[v][u] ) {//如果存在反向边则可以直接判断出冲突
incn = true;
stp = i;//记录关系数量
continue;
}
if ( g[u][v] ) continue;//表示该关系重复输入
//更新边和入度
g[u][v] = true;
deg[v]++;
memcpy(tmp_deg, deg, sizeof(deg));
switch ( topsort( n, tmp_deg ) ) {//拓扑排序
case 'D' :
detm = true;
stp = i;
break;
case 'I' :
incn = true;
stp = i;
break;
default : break;//未确定,还需等待下次关系输入后判断
}
}
if ( detm ) {//关系都输完后得出结论
printf("Sorted sequence determined after %d relations: ", stp);
while ( !ord.empty() ) {
putchar(ord.front());
ord.pop();
}
puts(".");
}
else if ( incn )
printf("Inconsistency found after %d relations.\n", stp);
else//即不矛盾也没有确定,那就是没确定
puts("Sorted sequence cannot be determined.");
}
return 0;
}
无注释代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define MAXN 26
using namespace std;
char deg[MAXN];
char tmp_deg[MAXN];
bool g[MAXN][MAXN];
char fmt[4];
queue<char> ord;
int
topsort( int n, char *deg ) {
int i;
int u, v;
bool nosure;
queue<char> que;
while ( !ord.empty() ) ord.pop();
for ( i = 0; i < n; i++ )
if ( !deg[i] ) que.push(i);
nosure = false;
while ( !que.empty() ) {
if ( que.size() > 1 ) nosure = true;
ord.push((u = que.front()) + 'A');
que.pop();
for ( v = 0; v < n; v++ )
if ( g[u][v] && !(--deg[v]) )
que.push(v);
}
if ( ord.size() < n ) return 'I';
if ( nosure ) return 'N';
return 'D';
}
int
main() {
int n, m;
int u, v;
int stp;
int i;
bool incn, detm;
while ( scanf("%d%d", &n, &m), n ) {
incn = false;
detm = false;
memset(g, false, sizeof(g));
memset(deg, 0, sizeof(deg));
for ( i = 1; i <= m; i++ ) {
scanf("%s", fmt);
if ( incn || detm ) continue;
u = fmt[0] - 'A';
v = fmt[2] - 'A';
if ( g[v][u] ) {
incn = true;
stp = i;
continue;
}
if ( g[u][v] ) continue;
g[u][v] = true;
deg[v]++;
memcpy(tmp_deg, deg, sizeof(deg));
switch ( topsort( n, tmp_deg ) ) {
case 'D' :
detm = true;
stp = i;
break;
case 'I' :
incn = true;
stp = i;
break;
default : break;
}
}
if ( detm ) {
printf("Sorted sequence determined after %d relations: ", stp);
while ( !ord.empty() ) {
putchar(ord.front());
ord.pop();
}
puts(".");
}
else if ( incn )
printf("Inconsistency found after %d relations.\n", stp);
else
puts("Sorted sequence cannot be determined.");
}
return 0;
}