POJ1094 Sorting It All Out

一.原题链接: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有环

如果在扫的过程的没有判断该字母是否出现过,就会输出不确定。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值