poj 1094 Sorting It All Out 拓扑排序

Sorting It All Out
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 26019 Accepted: 9009

Description
An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from smallest to largest. For example, the sorted sequence A, B, C, D implies that A < B, B < C and C < D. in this problem, we will give you a set of relations of the form A < B and ask you to determine whether a sorted order has been specified or not.

Input
Input consists of multiple problem instances. Each instance starts with a line containing two positive integers n and m. the first value indicated the number of objects to sort, where 2 <= n <= 26. The objects to be sorted will be the first n characters of the uppercase alphabet. The second value m indicates the number of relations of the form A < B which will be given in this problem instance. Next will be m lines, each containing one such relation consisting of three characters: an uppercase letter, the character "<" and a second uppercase letter. No letter will be outside the range of the first n letters of the alphabet. Values of n = m = 0 indicate end of input.

Output
For each problem instance, output consists of one line. This line should be one of the following three:

Sorted sequence determined after xxx relations: yyy...y.
Sorted sequence cannot be determined.
Inconsistency found after xxx relations.

where xxx is the number of relations processed at the time either a sorted sequence is determined or an inconsistency is found, whichever comes first, and yyy...y is the sorted, ascending sequence.

Sample Input

4 6
A<B
A<C
B<C
C<D
B<D
A<B
3 2
A<B
B<A
26 1
A<Z
0 0

Sample Output

Sorted sequence determined after 4 relations: ABCD.
Inconsistency found after 2 relations.

Sorted sequence cannot be determined.

==============================================================================

题目大意:给你若干条关系,表示n个点的前驱后继关系。n个点的名字是前n个大写字母。

逐句接入关系语句,一旦成功排序,无视后面的关系,按格式给出读到了第几个关系语句并从小到大输出字母序列。

一旦成环,即出现矛盾,无视后面的关系,按格式给出读到了第几个关系语句。

如果读完所有关系语句还不能确定大小序列输出特定的一句话。


解题思路:每读一句尝试一次拓扑排序即可。注意理清逻辑。


关于拓扑排序:思路简单就不专门写文章介绍了。

【用途】拓扑排序是用来把一个有向无环图(DAG)按照前驱比后继优先的顺序把各个点排成一列。
【流程】
①找到图中入度为0的点,这些点优先级相同,如果有处理这种优先级相同的排序方案,那么就按方案依次把这些点放进排序序列。然后把这些点以及跟这些点相连的边从图中删除。
②如果图中还有剩余的点,重复步骤①。
(如果有向图中有环,则不能进行拓扑排序,可以提前判断有向图是否有环,也可以在拓扑排序时提前跳出。跳出点在寻找入度为0的点之后,如果没有找到入度为0的点,图中又还有剩余的点,那么必定有环,跳出。)
//Memory: 564K	Time: 16MS

#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

const int N = 26;            //最多有26个点
bool g[N][N] , v[N];         //建立邻接矩阵并记录点是否可用
int n , ans[26];
enum State{OK,FAIL,NEXT};    //定义完成、失败和无法判定三种状态
State state;                 //用全局状态反映排序结果

void topologicSort()
{
    int ansNum = 0;
    int num = n;             //有n个点要排序
    state = OK;              //默认状态成功
    memset(v,true,sizeof(v));//所有点都可用,未被排除
    vector<int> p;           //vector存储入度为0的点
    while(num)               //所有点都被排除时停止循环
    {
        for( int i = 0 ; i < n ; i++ )
            if(v[i])         //在可用的点中寻找入度为0的点
            {
                bool in = false;
                for( int j = 0 ; j < n ; j++ )
                    if(v[j] && g[j][i])  //前驱点可用才算入度
                    {
                        in = true;       //找到一个入度则入度不为0
                        break;
                    }
                if(!in)                  //如果入度为0则压入点集p
                    p.push_back(i);
            }
        if(p.size() > 1)                 //如果入度为0的点不止一个
            state = NEXT;                //则还无法完成排序
        else if(p.empty() && num)        //如果没有入度为0的点
        {                                //但是仍有剩余的点
            state = FAIL;                //则存在环,判定排序失败
            return;
        }
        while(!p.empty())                //如果有入度为0的点
        {
            v[p.back()] = false;         //标记为不可用
            ans[ansNum++] = p.back();    //保存答案序列
            p.pop_back();                //弹出入度为0的点集
            num--;                       //未被排除的点数减1
        }
    }
}

int main()
{
    int m;
    while( scanf("%d%d", &n, &m) , n )
    {
        memset(g,false,sizeof(g));           //初始化邻接矩阵
        int rNum;
        for( int i = 1 ; i <= m ; i++ )
        {
            char str[4];
            scanf("%s", str);                //逐句接入关系
            g[str[0]-'A'][str[2]-'A'] = true;//填入邻接矩阵
            topologicSort();                 //尝试拓扑排序
            if( state != NEXT )              //如果能够判定
            {
                rNum = i;                    //记录当前关系序号
                for( ; i < m ; i++ )         //接入剩余关系
                    scanf("%s", str);
            }
        }
        if( state == OK )
        {
            printf("Sorted sequence determined after %d relations: ", rNum);
            for( int i = 0 ; i < n ; i++ )
                printf("%c", 'A'+ans[i]);
            printf(".\n");
        }
        else if( state == FAIL )
            printf("Inconsistency found after %d relations.\n", rNum);
        else
            printf("Sorted sequence cannot be determined.\n");
    }
    return 0;
}
discuss里有个大大把oj的检测数据跟答案贴出来了。。。还有人用现成数据打表过了给跪orz

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值