POJ 1094 Sort it all out

Output
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.

给出一系列字母中的大小关系,根据所给关系,如果能确定字母的顺序,输出字母的顺序和最早能在第几次输入中确定,如果不能确定,输出不能确定关系,如果不存在这样的字母序列,输出最早能在第几次输入中确定。
根据题意,可以确定采用在线处理的拓扑排序找出事件发生的顺序。在使用拓扑排序前,要首先确定所给的图是否有环,即是否存在这样一个字母序列,这里采用Floyd变形计算节点与节点之间的连接关系。最后在拓扑排序中,每一次有且仅能有一个入度为0的节点,如果存在两个入度为0的节点,那么这两个节点的先后顺序不能确定,导致整个字母序列不能确定

#include <stdio.h>
#include <cstring>
#include <vector>
#include <queue>
#include <utility>
#include <map>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;

int N,M;
int amount;
int deg[32],temp[32];
char ans[32];
bool adj[32][32];
queue<int> Q;
vector<int> E[32];
bool topSort();
inline bool getLoop();      //If there is loop,return true;if not return false
inline bool getRep(int star,int finish);        //If the input is reiterated  with ones we stored ,return false
inline int inquire(char k);
int main(){
    while(true){
        scanf("%d %d",&N,&M);
        if(N+M==0)
            break;
        for(register int i=0;i<N;i++)
            deg[i]=0;
        for(register int i=0;i<N;i++)
            for(register int j=0;j<N;j++)
                adj[i][j]=false;
        for(register int i=0;i<N;i++)
            E[i].clear();
        int flag=-1;            //record what case happened
        int num;
        bool symbol=true;       //continue record input data
        char A,B,C;
        int star,finish;
        for(register int i=1;i<=M;i++){
            getchar();
            scanf("%c%c%c",&A,&B,&C);
            if(!symbol)
                continue;
            star=C-'A',finish=A-'A';
            if(getRep(star,finish)){
                E[star].push_back(finish);
            }
            else
                continue;
            deg[finish]++;
            memcpy(temp,deg,sizeof(deg));
            adj[star][finish]=true;
            if(getLoop()){
                symbol=false;
                flag=2;         //Second case:exist a loop
                num=i;
            }
            if(topSort()&&amount==N){     //false
                flag=1;
                num=i;
                symbol=false;
            }
            memcpy(deg,temp,sizeof(temp));
        }
        if(flag==-1)
            flag=3;
        switch(flag){
        case 1:
            printf("Sorted sequence determined after %d relations: ",num);
            for(register int i=N-1;i>=0;i--)
                printf("%c",ans[i]);
            printf(".\n");
            break;
        case 2:
            printf("Inconsistency found after %d relations.\n",num);
            break;
        case 3:
            printf("Sorted sequence cannot be determined.\n");
            break;
        }
    }
    return 0;
}
bool topSort(){
    amount=0;
    while(!Q.empty())
        Q.pop();
    for(register int i=1;i<N;i++)
        if(deg[i]==0){
            Q.push(i);
            ans[amount]=i+'A';
            amount++;
        }
    int now;
    while(!Q.empty()){
        if(Q.size()>1)
            return false;
        now=Q.front();
        Q.pop();
        for(register int i=0;i<E[now].size();i++){
            deg[E[now][i]]--;
            if(deg[E[now][i]]==0){
                ans[amount]=E[now][i]+'A';
                amount++;
                Q.push(E[now][i]);
            }
        }
    }
    return true;
}
inline bool getLoop(){
    for(register int i=0;i<N;i++)
        for(register int j=0;j<N;j++)
            for(register int k=0;k<N;k++)
                if(!adj[i][j]&adj[i][k]&adj[k][j])  //i and j is not connected
                    adj[i][j]=true;             //Second i point to k,and k point to j
    for(register int i=0;i<N;i++)
        if(adj[i][i])                       //i can reach i.It mean exist loop
            return true;
    return false;
}
inline bool getRep(int star,int finish){
    if(E[star].size()==0)
        return true;
    else
        for(register int i=0;i<E[star].size();i++)
            if(E[star][i]==finish)
                return false;
    return true;
}

可能的错误情况

  • 未考虑重边
    这样可能造成输入时节点入度记录出现重复,影响拓扑排序的过程

  • 变量的初始化
    由于使用变量过多,可能有所遗漏

  • 节点入度记录
    由于进行在线处理,一次对于每一次输入都要进行拓扑排序。这必将改变记录节点入度的数组,但下一次对节点入度的记录需要建立在上一次记录节点数组不变的基础上。因此,在每次拓扑排序前,需要拷贝记录节点入度的数组,并在本次拓扑排序结束后,还原记录节点入度的数组


测试数据

4 8
A<B
A<B
A<B
A<C
B<C
C<D
B<D
A<B
Sorted sequence determined after 6 relations: ABCD.

4 6
A<B
A<C
B<C
C<D
B<D
A<B
Sorted sequence determined after 4 relations: ABCD.

4 3
B<D
C<D
D<E
Sorted sequence cannot be determined.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值