题目:http://poj.org/problem?id=1094
看到此题,首先觉得这是一种层层递进的关系,所以可以想到用拓扑排序;
就像人工排序,每次需要找到一个最小的,再找到新的最小的……所以用有向边代表小的元素到大的元素的关系,每次的入度为0的点就是最小的;
出现错误也就是出现了环,可以看做是拓扑排序过程后还有没有被排到的点,也就是怎样入度都不为0;
因为要输出哪一步,所以就一步一步,每一步上建图、判断等等;
注意因为上一步不能影响下一步,所以排序中不能把真的入度减去。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; priority_queue<int,vector<int>,greater<int> >q; int n,m,reg[30],ans[30],num,tmp[30]; bool sid[30][30],f0,f1; char dc[5]; int per() { memset(ans,0,sizeof ans); while(q.size())q.pop(); for(int i=1;i<=n;i++) if(!reg[i])q.push(i);// memcpy(tmp,reg,sizeof reg);//!!!注意别影响全局 num=0; bool flag=0; while(q.size()) { if(q.size()>1)flag=1;//有超过一个入度为0的点 int x=q.top();q.pop(); ans[++num]=x; for(int i=1;i<=n;i++) if(sid[x][i]) { tmp[i]--; if(!tmp[i])q.push(i); } } if(num<n)return 0;//即使不完全也应该有n个,否则有环 if(flag)return -1;//可能还没完全 return 1; } int main() { while(scanf("%d%d",&n,&m)==2) { if(!n&&!m)return 0; memset(sid,0,sizeof sid); memset(reg,0,sizeof reg); f0=0;f1=0; for(int i=1;i<=m;i++) { cin>>dc; if(f0||f1)continue; if(sid[dc[2]-‘A‘+1][dc[0]-‘A‘+1]) { f0=1; printf("Inconsistency found after %d relations.\n",i); continue; } if(!sid[dc[0]-‘A‘+1][dc[2]-‘A‘+1])//!!! { sid[dc[0]-‘A‘+1][dc[2]-‘A‘+1]=1; reg[dc[2]-‘A‘+1]++; } int k=per(); if(!k) { f0=1; printf("Inconsistency found after %d relations.\n",i); } if(k==1) { f1=1; printf("Sorted sequence determined after %d relations: ",i); for(int i=1;i<=n;i++) printf("%c",char(ans[i]+‘A‘-1)); printf(".\n"); } } if(!f0&&!f1) printf("Sorted sequence cannot be determined.\n"); } }