一.原题链接: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有环
如果在扫的过程的没有判断该字母是否出现过,就会输出不确定。