OJ 1094 Sorting It All Out练习小结

  1. 注意三种情况的 优先级:不确定<顺序排列<矛盾
  2. 在入度为0的点数大于1时,第一反应是序列暂时不能确定,但还可能存在之后输入的式子与之前输入矛盾的情况!这个时候不能直接返回stata=‘不确定’!一定要把所有式子遍历完,找到是否存在矛盾!
  3. 最简单的思路就是把26个字符的大小情况用矩阵存储,-1表示大于,0表示未知,1表示小于。
#include <iostream>
#include <stack>
#define MAX 26
using namespace std;
// AC了!
char sorted[MAX+1];//+1用于赋结束符
int top(int n,int letter[MAX][MAX],int g[]);
int main()
{
    int letter[MAX][MAX];//-1:已得到小于不等式,0:未知,1:小于
    int n,m,state,mm;
    char formula[4];
    int g[MAX];//保存每个点的入度

    while(cin>>n>>m && n!=0 && m!=0){
        state = 0;
        if(m<(n-1)){//若公式数小于n-1一定不可能得到确定的排序
            state = 2;//无法确定情况
            while(m--){
                cin>>formula;
            }
        }
        else{
            for(int i=0;i<n;i++){
                    g[i] = 0;//初始化每个点的入度为0
                for(int j=0;j<n;j++)
                    letter[i][j]=0;
            }
           bool change = false;
           for(int i=0;i<m;i++){
                cin>>formula;
                //在state==3的情况下,state可以确定下来,否则随着式子的增加,state可能改变
                //当能确定下排列顺序时state=1,之后的式子也可以不管了,不管之后会不会出现矛盾
                if(state==0||state==2){
                    int a=formula[0]-'A';
                    int b=formula[2]-'A';
                    if(letter[a][b] != -1){
                        letter[a][b] = 1;
                        letter[b][a] = -1;
                        g[b]++;//点b入度加1
                        state = top(n,letter,g);//对当前输入的式子进行拓扑排序
                    }else{
                        state = 3;//出现矛盾
                    }
                }//end if
                if(!change && (state == 3)){
                    mm = i+1;
                    change = true;//确保mm是最小值

                }else if(!change && state == 1){
                    mm = i+1;
                    change = true;//确保mm是最小值
                }
            }
     }

        switch(state){
            case 1:
                cout<<"Sorted sequence determined after "<<mm<<" relations: ";
                for(int i=0;i<n;i++)
                    cout<<sorted[i];
                cout<<"."<<endl;
                break;
            case 2:
                cout<<"Sorted sequence cannot be determined."<<endl;
                break;
            case 3:
                cout<<"Inconsistency found after "<<mm<<" relations."<<endl;
                break;
            default:
                cout<<"WRONG"<<endl;
                break;
        }


    }
    return 0;
}

//拓扑排序
int top(int n,int letter[MAX][MAX],int g[MAX]){
    stack<int> s;
    int top;
    int sum=0;
    int ispush[MAX];
    int let[MAX][MAX];
    for(int i=0;i<n;i++){
        ispush[i]=g[i];
        for(int j=0;j<n;j++)
            let[i][j]=letter[i][j];
    }
    for(int i=0;i<n;i++){
        if(ispush[i]==0){
            s.push(i);
            ispush[i] = -1 ;//标记为以及入栈过的点
        }
    }

    int flag =0;
    while(!s.empty()){
        ///如果入度为0的点大于1,则无法确定排序。一定不能直接返回state=2!!
        ///因为还有存在式子矛盾的情况!!!!这个的优先级是最大的!
        if(s.size()>1)
           flag = 1;
        top = s.top();
        s.pop();
        sorted[sum++] = top+'A';
        for(int i=0;i<n;i++){
            if(let[top][i]==1){
                ispush[i]--;//入度减1
                if(ispush[i]<(-1))//说明出现环
                    return 3;
                let[i][top] = 0;//删掉连接边
            }
        }
        for(int i=0;i<n;i++){
            if(ispush[i]==0){
                s.push(i);
                ispush[i] = -1;
            }
        }
    }
    sorted[sum] = '\0';//赋结束符结束该字串
     if(sum!=n)
        return 3;//有环
     else if(flag==1)//不确定的拓扑排序
        return 2;
    return 1;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值