题目大意:
对于给定的前n个字母( A-... ),给出可能的字母间的偏序,问是否能确定构成一个线性序T,如果能或不能,则给出最早能做出判断的偏序在第几个。否则说明不可判。
这道题有点犀利,弄了半个晚上。一开始思维没打开,找不到思路,最后想到判断可达性的复杂度不可能比DFS传递闭包更好,因此果断改变思路。可以顺序读入每个偏序,对于每次读入,构造一次拓扑排序,那么在第几个偏序出解,结果就在第几。
注意容易出现的逻辑错误,首先就是“判断是否能构成T序”的优先级高于T是否唯一,也就是说当出现多个可随意次序的点时,不能马上输出不唯一,需要将拓扑排序做完以保证没有成环,判环优先级更高。
算法可以顺序读入偏序,随之做拓扑拆边,当遇到栈尺寸大于1(多个不可比),不可比标记置一。拓扑结束后,若成环,则输出成环,否则输出T唯一或继续读入偏序(当前不唯一)。若始终不成环且不唯一,最终结果自然不唯一。
4 4
A<B
C<B
D<B
B<A
Inconsistency found after 4 relations.
1
#include<cstdio>
2
#include<cstdlib>
3
#include<cstring>
4
#include<stack>
5
using namespace std;
6
int g[26][26],degree[26],degreeR[26],path[26];
7
bool ring,more;
8
int n,m;
9
int main()
{
10
int i,j,k,t;
11
char u,v;
12
int ele;
13
bool sure,unsure;
14
while(scanf("%d%d",&n,&m),n|m)
{
15
memset(g,0,sizeof(g));
16
memset(degreeR,0,sizeof(degreeR));
17
sure = false;
18
for(getchar(),i=0;i<m;i++)
{
19
scanf("%c<%c",&u,&v);getchar();
20
21
g[ u-'A' ][ v-'A' ]=1;
22
degreeR[ v-'A' ]++;
23
stack<int> _sta;
24
for(j=0;j<n;j++) if( degreeR[j] == 0 ) _sta.push(j);
25
26
for(j=0;j<n;j++) degree[j]=degreeR[j];
27
more=false;
28
ring=false;
29
for(j=0;j<n;j++)
{
30
if( _sta.size()>1 ) more=true; // unsure
31
if( _sta.empty() )
{ ring=true; break; } // ring
32
ele = _sta.top(); _sta.pop();
33
path[j]=ele;
34
for(k=0;k<n;k++)
{
35
if( g[ele][k]!=0 && --degree[k] == 0 )
{ _sta.push(k); }
36
}
37
}
38
39
if( j == n && more == false)
{
40
printf("Sorted sequence determined after %d relations: ",i+1);
41
for(j=0;j<n;j++) printf("%c",'A'+path[j]); printf(".\n");
42
sure=true;
43
break;
44
}
45
else if( ring == true )
{ printf("Inconsistency found after %d relations.\n",i+1); sure=true; break; }
46
}
47
if( sure == false ) printf("Sorted sequence cannot be determined.\n");
48
for(t=i+1;t<m;t++)
{ scanf("%c<%c",&u,&v); getchar(); }
49
}
50
return 0;
51
}
52