一.原题链接:http://poj.org/problem?id=1094
二.题目大意:给你二十六个字母中前n个的两两大小顺序,让你判断一下三种情况:
1.输入某一对之后,已经能够判断出矛盾,即存在类似A<B, B<C, 但是A>C的情况。
2.输入某一对之后,已经能够得出所有的前n个字母的大小顺序。
3.所有对输完之后,还是不能判断前n个字母的大小顺序。
三,思路:用拓扑排序来做,记住拓扑排序不是简单判断有没有环,而且还要判断是否前n个字母都可以排序。
而要做到这一点,
首先,每次读入都要进行一次拓扑排序。
其次,每次扫那个入度的数组的时候,计数统计入度为0的节点有几个。
有且只有有1个:说明它的大小位置是唯一的,它一定排在所有未出队的其他元素之前。
0个:说明队列空了,这时一定有环。
大于1个:说明它大小位置不唯一。
然后,如果大小位置唯一,返回其被删除的节点数目,如果这个数目等于要排序的数目,那么结束,记录其数目。
也就是说,要得出可以排序的苛刻条件是:
1.所有点都要给出。
2.之前没有环。
3,当次遍历记录入度的数组,每次都有且只有一个入度为0的节点,直到当前的点都被删完。
四.注意事项:
题目意思是中间如果产生结果,以后的输入都是垃圾输入。也就是说,如果中间已经发现能够排序了,那么就算后面有输入让它成环,那也还是输出那个中间可以排序的结果。
因此,要先判断是否有环和能否排序,如果到最后还不能排序,输出那个不能排序的结果。
五.代码:
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; const int MAX_SIZE = 26, INF = 0x3f3f3f3f; int cnt[MAX_SIZE], nodeNum, edgeNum; vector <vector<int> >mp; bool alpha[MAX_SIZE]; char str[MAX_SIZE]; int TopoSort(int cntShow) { int i, j, c, tempCnt[MAX_SIZE], cur, builtNum, num, savej; for(i = 0; i < nodeNum; i++) tempCnt[i] = cnt[i]; bool able = true; c = 0; for(i = 0; i < cntShow; i++){ num = 0; for(j = 0; j < nodeNum; j++) if(0 == tempCnt[j] && alpha[j]){ num++; cur = j; } if(num == 0) return -1; //有环 if(num > 1) able = false; //无序 for(j = 0; j < mp[cur].size(); j++) tempCnt[mp[cur][j]]--; str[c++] = cur + 'A'; str[c] = 0; tempCnt[cur] = -1; } if(able){ return c; } else return 0; } int main() { //freopen("in.txt", "r", stdin); int i, j, determined, cntShow, savei, sign; bool stop; char relation[3]; while(cin>>nodeNum>>edgeNum && nodeNum && edgeNum){ memset(cnt, 0, sizeof(cnt)); memset(alpha, 0, sizeof(alpha)); memset(str, 0, sizeof(str)); mp.clear(); mp.resize(MAX_SIZE); cntShow = 0; determined = 0; stop = false; for(i = 1; i <= edgeNum; i++){ cin>>relation; cnt[relation[2] - 'A']++; mp[relation[0] - 'A'].push_back(relation[2] - 'A'); if(!alpha[relation[0] - 'A']){ cntShow++; alpha[relation[0] - 'A'] = true; } if(!alpha[relation[2] - 'A']){ cntShow++; alpha[relation[2] - 'A'] = true; } if(!stop){ sign = TopoSort(cntShow); } if(-1 == sign && !stop){ savei = i; determined = -1; stop = true; } if(sign == nodeNum && !stop){ savei = i; determined = 1; stop = true; } } switch(determined) { case -1: printf("Inconsistency found after %d relations.\n", savei); break; case 0: printf("Sorted sequence cannot be determined.\n"); break; case 1: printf("Sorted sequence determined after %d relations: %s.\n", savei, str); break; } } return 0; }
这里我再给出一组:
6 2
A<B
B<A
输出在2有环
如果在扫的过程的没有判断该字母是否出现过,就会输出不确定。