POJ 1094 Sorting It All Out (拓扑排序)

把每个X<Y连一条X到Y的边,然后在这个图上做拓扑排序。

如果发现有环,说明出现了不合法情况;

如果没有环,且拓扑排序过程中queue中元素从未超过两个(保证拓扑路径唯一性),且拓扑路径长度为N,说明关系确定了;

否则是未确定状态。


拓扑排序过程如下:

1.用一个queue保存可能在拓扑路径中的点

2.初始化时把所有入度为0的点加入queue

3.每次先判断queue中元素是否有多个,如果有,当前状态不可能是确定状态。然后取队首元素,出队,把这个点加入到答案中。

4.把和这个元素相连的,且没入过queue的点的入度减1,如果为0了,就把这个点入queue。

5.queue为空时结束3,4,判断答案中的点数是否小于当前图中点数,如果是说明有环。如果点数等于N,且拓扑排序过程中queue中元素从未超过两个,说明已确定。否则是未确定状态


代码:

//
//  main.cpp
//  1094 Sorting It All Out
//
//  Created by Baoli1100 on 15/4/8.
//  Copyright (c) 2015年 Baoli1100. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#include <queue>
int a[30];
int N,M;
int m[30][30];
int c[30][30];
int d[30];
bool cur[30];
queue<int> res;

int topo(){
    while(!res.empty()){
        res.pop();
    }
    int Num=0;
    queue<int> topo;
    bool vis[30];
    memset(vis,0,sizeof(vis));
    for(int i=0;i<30;i++){
        d[i]=a[i];
        if(!d[i]&&cur[i]){
            topo.push(i);
            vis[i]=1;
        }
        if(cur[i]) Num++;
    }
    bool flag=0;
    
    while(!topo.empty()){
        if(topo.size()>1) flag=1;
        int cur=topo.front();
        topo.pop();
        res.push(cur);
        for(int i=0;i<N;i++){
            if(m[cur][i]&&!vis[i]){
                d[i]--;
                if(!d[i]){
                    topo.push(i);
                    vis[i]=1;
                }
            }
        }
    }
    if(res.size()<Num) return -1;
    else if(!flag&&res.size()==N)return 1;
    else return 0;
}


int main(){
    while(~scanf("%d%d",&N,&M)){
        if(!N&&!M) break;
        memset(a,0,sizeof(a));
        memset(m,0,sizeof(m));
        memset(cur,0,sizeof(cur));
        bool flag =0;
        for(int i=0;i<M;i++){
            char k[10];
            scanf("%s",k);
            if(flag) continue;
            char s=k[0];
            char t=k[2];
            cur[s-'A']=1;
            cur[t-'A']=1;
            m[s-'A'][t-'A']=1;
            a[t-'A']++;

            int ans=topo();
            if(ans==1){
                flag=1;
                printf("Sorted sequence determined after %d relations: ",i+1);
                while(!res.empty()){
                    printf("%c",res.front()+'A');
                    res.pop();
                }
                printf(".\n");
            }
            if(ans==-1){
                flag=1;
                printf("Inconsistency found after %d relations.\n",i+1);
            }
        }
        if(!flag){
            printf("Sorted sequence cannot be determined.\n");
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值