题意:
给定一组字母的大小关系判断他们是否能组成唯一的拓扑序列。是典型的拓扑排序,但输出格式上确有三种形式:
1.该字母序列有序,并依次输出;
2.该序列不能判断是否有序;
3.该序列字母次序之间有矛盾,即有环存在。
分析:每次加入一条边,进行一次拓扑排序,判断是否可以唯一确定序列(唯一的话就是每次选点只有一个选择),是否矛盾(即有环,判断入队的数量即可,无环的话每个点都会入队一次)。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<stack> #include<map> #include<vector> #include<queue> using namespace std; const int N=27; int in[N],inq[N]; //入度 int g[N][N]; //判断是否有边 int ans[N]; //保存排序结果 int n,m; int toposort() { memcpy(inq,in,sizeof(in)); queue<int>q; for(int i=0;i<n;i++)if(!inq[i])q.push(i); bool flag=0; int cnt=0; while(!q.empty()){ if(q.size()>1)flag=1; //如果队列中有多个可选点,那么排序就不能唯一确定 int t=q.front();q.pop(); ans[cnt++]=t; for(int i=0;i<n;i++){ if(g[t][i]){ inq[i]--; if(!inq[i])q.push(i); } } } if(cnt!=n)return 0; //有环 if(!flag)return 1; //序列唯一 return 2; //拓扑排序 } int main() { char s[10]; while(~scanf("%d%d",&n,&m)&&(n+m)){ memset(in,0,sizeof(in)); memset(g,0,sizeof(g)); int i; for(i=1;i<=m;i++){ scanf("%s",s); in[s[2]-'A']++; g[s[0]-'A'][s[2]-'A']=1; int t=toposort(); if(t==0){ printf("Inconsistency found after %d relations. ",i); break; } else if(t==1){ printf("Sorted sequence determined after %d relations: ",i); for(int j=0;j<n;j++)printf("%c",(char)('A'+ans[j])); printf(". ");break; } } if(i>m)printf("Sorted sequence cannot be determined. "); else for(i=i+1;i<=m;i++)scanf("%s",s); } return 0; }