把每个X<Y连一条X到Y的边,然后在这个图上做拓扑排序。
如果发现有环,说明出现了不合法情况;
如果没有环,且拓扑排序过程中queue中元素从未超过两个(保证拓扑路径唯一性),且拓扑路径长度为N,说明关系确定了;
否则是未确定状态。
拓扑排序过程如下:
1.用一个queue保存可能在拓扑路径中的点
2.初始化时把所有入度为0的点加入queue
3.每次先判断queue中元素是否有多个,如果有,当前状态不可能是确定状态。然后取队首元素,出队,把这个点加入到答案中。
4.把和这个元素相连的,且没入过queue的点的入度减1,如果为0了,就把这个点入queue。
5.queue为空时结束3,4,判断答案中的点数是否小于当前图中点数,如果是说明有环。如果点数等于N,且拓扑排序过程中queue中元素从未超过两个,说明已确定。否则是未确定状态
代码:
//
// main.cpp
// 1094 Sorting It All Out
//
// Created by Baoli1100 on 15/4/8.
// Copyright (c) 2015年 Baoli1100. All rights reserved.
//
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#include <queue>
int a[30];
int N,M;
int m[30][30];
int c[30][30];
int d[30];
bool cur[30];
queue<int> res;
int topo(){
while(!res.empty()){
res.pop();
}
int Num=0;
queue<int> topo;
bool vis[30];
memset(vis,0,sizeof(vis));
for(int i=0;i<30;i++){
d[i]=a[i];
if(!d[i]&&cur[i]){
topo.push(i);
vis[i]=1;
}
if(cur[i]) Num++;
}
bool flag=0;
while(!topo.empty()){
if(topo.size()>1) flag=1;
int cur=topo.front();
topo.pop();
res.push(cur);
for(int i=0;i<N;i++){
if(m[cur][i]&&!vis[i]){
d[i]--;
if(!d[i]){
topo.push(i);
vis[i]=1;
}
}
}
}
if(res.size()<Num) return -1;
else if(!flag&&res.size()==N)return 1;
else return 0;
}
int main(){
while(~scanf("%d%d",&N,&M)){
if(!N&&!M) break;
memset(a,0,sizeof(a));
memset(m,0,sizeof(m));
memset(cur,0,sizeof(cur));
bool flag =0;
for(int i=0;i<M;i++){
char k[10];
scanf("%s",k);
if(flag) continue;
char s=k[0];
char t=k[2];
cur[s-'A']=1;
cur[t-'A']=1;
m[s-'A'][t-'A']=1;
a[t-'A']++;
int ans=topo();
if(ans==1){
flag=1;
printf("Sorted sequence determined after %d relations: ",i+1);
while(!res.empty()){
printf("%c",res.front()+'A');
res.pop();
}
printf(".\n");
}
if(ans==-1){
flag=1;
printf("Inconsistency found after %d relations.\n",i+1);
}
}
if(!flag){
printf("Sorted sequence cannot be determined.\n");
}
}
return 0;
}