Sorting It All Out
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. Source |
当然要建图。。一开始准备用dfs跑下去,dfs的思路是这样的:每加入一条边,若已确定有唯一的顺序或存在矛盾解就不管他,否则就对所有的点dfs,每访问过一个点就标记下来,若后来访问的点能再次访问已标记的点(存在环)则说明此序列是矛盾的,最终的结果也一定是矛盾的;若能够找到找到一个解,且此解的长度刚好是n,则说明结果一定是存在唯一解。关键是那种存在多解的情况,找到一个解,此解的长度 <n ,不能说明当前已有的边为多解,还可能是矛盾!例如 存在图: 1->2,3->4,4->5,5->3.以1为起点开始dfs 无论如何也检测不到3,4,5的那个环,这就决定了我们必须要对图中当前入度为0的节点全都dfs一次。另外还有一些细节问题,如:进行下一次dfs前,就要判断当前点所能到的所有点是否已标记,是则返回矛盾的解。。。顿时崩溃了。早已写了好长。难道天要亡我~~。只能回到传统的拓扑排序解法。
【思路】
每加入一条边,就拓扑排序一次,拓扑排序的时候要删除入度,排完序要恢复,关键是判断是否有多解,代码中说明
【代码】
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n;
int R[30][30];
int rudu[30],trudu[30];
int Q[30];
int topo[30],ntopo;
char ansr[30];
void copytopo()
{
for(int i=0;i<n;i++)
ansr[i]=topo[i]+'A';
ansr[n]=0;
}
void copyrudu()
{
for(int i=0;i<n;i++)
trudu[i]=rudu[i];
}
int toposort()
{
ntopo=0;
int front=0,rear=0;
for(int i=0;i<n;i++)
if(rudu[i]==0)
Q[rear++]=i;
copyrudu();
if(rear==0)return 2;
int p2=rear;//表示可能为多解
while(front<rear)
{
int temp=Q[front++];
topo[ntopo++]=temp;
int cnt=0;
for(int i=0;i<n;i++)
{
if(R[temp][i]&&!(--trudu[i]))
{
Q[rear++]=i;
cnt++;
}
}
if(cnt>1)p2=2;//一下子有多个入度为0的点入队,即表明可能为多解
}
for(int i=0;i<n;i++)
if(trudu[i])
return 2;//若存在入度还不为0的点,就一定有环!
if(p2>1)return 0;
if(ntopo==n)
{
copytopo();//有唯一解就赋给终解
return 1;
}
return 0;
}
int main()
{
int m;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)break;
memset(R,0,sizeof(R));
memset(rudu,0,sizeof(rudu));
int flag=0;//1表示有唯一解,2表示有矛盾的解;
int ans;
for(int i=1;i<=m;i++)
{
char S[10];
scanf("%s",S);
if(flag)continue;//唯一解和矛盾解都不管
ans=i;
if(!R[S[0]-'A'][S[2]-'A'])//有重边
rudu[S[2]-'A']++;
R[S[0]-'A'][S[2]-'A']=1;
flag=toposort();
}
if(!flag)
printf("Sorted sequence cannot be determined.\n");
else
{
if(flag==1)
printf("Sorted sequence determined after %d relations: %s.\n",ans,ansr);
else
printf("Inconsistency found after %d relations.\n",ans);
}
}
}
最后还因为输出WA两次。。OMG