题解 拓扑排序 POJ 1094
题意:给你一些大写字母间的偏序关系,然后让你判断能否唯一确定它们之间的关系,或者所给关系是矛盾的,或者到最后也不能确定它们之间的关系。
分析:
用拓扑排序:
1.拓扑排序可以用栈来实现,每次入栈的是入度为0的节点。
1.拓扑排序的结果一般分为三种情况:1、可以判断 2、有环出现了矛盾 3、条件不足,不能判断.
2.这道题不仅需要判断这三种情况,而且还要判断在处理第几个关系时出现前两种情况,对于本道题来说三种情况是有优先级的。前两种情况是平等的谁先出现先输出谁的相应结果,对于第三种情况是在前两种情况下都没有的前提下输出相应结果的.
网上对于这道题的错误提示:
1.本题顺序:
a.先判有没有环,有环就直接输出不能确定;
b.如果没有环,那么就看会不会有多种情况,如果有多种情况就再读下一行;如果全部行读完还是有多种情况,就是确定不了;
c.如果最后没有环,也不存在多种情况(即每次取出来入度为零的点只有一个),那么才是答案;
2.有答案就先出答案,不管后面的会不会矛盾什么的;
3.如果在没有读完所有输入就能出答案,一定要把剩下的行都读完。
代码
#include <iostream> #include <cstdio> #include <string.h> #include <stack> using namespace std; const int MAX=27; int graph[MAX][MAX],indegree[MAX],rem[MAX]; int n,m; int toposort(int n) { int in[MAX]; memcpy(in,indegree,sizeof(indegree)); stack<int > s; int i; for(i=0;i<n;i++) if(in[i]==0) s.push(i); int flag=0; int t,j=0; while(!s.empty()) { if(s.size()>1) flag=1; t=s.top(); s.pop(); rem[j++]=t; for(i=0;i<n;i++) if(graph[t][i]!=0) if(--in[i]==0) s.push(i); } if(j!=n) return 1; else if(flag==1) return 2; return 0; } int main() { int i,j,res=0; int incon,deter; char a,b; while(scanf("%d%d",&n,&m)&&n!=0&&m!=0) { getchar(); incon=0; deter=0; memset(graph,0,sizeof(graph)); memset(indegree,0,sizeof(indegree)); for(i=1;i<=m;i++) { scanf("%c<%c",&a,&b); getchar(); if(!incon&&!deter) { if(graph[b-'A'][a-'A']==1) { incon=1; printf("Inconsistency found after %d relations.\n",i); continue; } if(graph[a-'A'][b-'A']==0) { graph[a-'A'][b-'A']=1; indegree[b-'A']++; } /*cout<<1;*/ res=toposort(n); if(res==0) { printf("Sorted sequence determined after %d relations: ",i); for(j=0;j<n;j++) printf("%c",rem[j]+'A'); printf(".\n"); deter=1; } else if(res==1) { printf("Inconsistency found after %d relations.\n",i); incon=1; } } } if(!deter && !incon) printf("Sorted sequence cannot be determined.\n"); } return 0; }