POJ 1094 Sorting It All Out(拓扑排序)
http://poj.org/problem?id=1094
题意:
给你字母表的前N个大写字母和M个大小关系(即有向边)。所有的边按顺序给你,要你在能判断出全序或矛盾的时候及时输出(即当输入i条边的时候,出现了有向环或已经全序了,那么应该及时输出,),或者直到最后也不能出现全序。
分析:
我们只需要对于每一条边(共M条有向边)都调用一次topo排序,看看能否出现结果或者出现矛盾即可.
如果能topo排序就说明没有矛盾,但是可能是全序或者偏序集.如果是全序集,那么topo排序的过程中,入度为0的点始终只会存在1个.
AC代码:
#include<cstdio> #include<cstring> #include<queue> #include<vector> using namespace std; const int maxn=26+5; vector<int> G[maxn]; int in[maxn]; int n,m; char order[1000][10]; char ans[maxn]; int cnt;//记录ans中当前字母 int topo() { cnt=0; queue<int> Q; int indegree[maxn]; //错误1,这里要重新用一个入度数组 memcpy(indegree,in,sizeof(in)); bool all_order=true;//全序标记 for(int i=0;i<n;i++)if(indegree[i]==0) Q.push(i); //错误2,忘了入度0才入队列 while(!Q.empty()) { if(Q.size()>1) all_order=false;//Q中始终只有1个元素才能保证全序 int u=Q.front(); Q.pop(); ans[cnt++]=u+'A'; for(int i=0; i<G[u].size(); i++) { int v=G[u][i]; if(--indegree[v]==0) Q.push(v); } } int result = 0; if(cnt<n) result = -1;//存在环 else if(all_order==true) result=1;//已然全序 return result; } int main() { while(scanf("%d%d",&n,&m)==2&&n) { memset(in,0,sizeof(in)); for(int i=0;i<n;i++) G[i].clear(); for(int i=0;i<m;i++) scanf("%s",order[i]); int flag=0,i; for(i=0;i<m;i++) { int u=order[i][0]-'A', v=order[i][2]-'A'; G[u].push_back(v); in[v]++; if( (flag=topo())!=0) break; } ans[n]=0; //错误,这句没加,这个错误很难找 if(flag==1) printf("Sorted sequence determined after %d relations: %s.\n",i+1,ans); else if(flag==0) printf("Sorted sequence cannot be determined.\n"); else if(flag==-1) printf("Inconsistency found after %d relations.\n",i+1); } return 0; }