poj 1094 简单拓扑排序

题意:

给定一组字母的大小关系判断他们是否能组成唯一的拓扑序列。是典型的拓扑排序,但输出格式上确有三种形式:

   1.该字母序列有序,并依次输出;

   2.该序列不能判断是否有序;

   3.该序列字母次序之间有矛盾,即有环存在。

分析:

每次加入一条边,进行一次拓扑排序,判断是否可以唯一确定序列(唯一的话就是每次选点只有一个选择),是否矛盾(即有环,判断入队的数量即可,无环的话每个点都会入队一次)。




#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
#include<map>
#include<vector>
#include<queue>
using namespace std;
const int N=27;
int in[N],inq[N]; //入度
int g[N][N]; //判断是否有边
int ans[N]; //保存排序结果
int n,m;
int toposort()
{
    memcpy(inq,in,sizeof(in));
    queue<int>q;
    for(int i=0;i<n;i++)if(!inq[i])q.push(i);
    bool flag=0;
    int cnt=0;
    while(!q.empty()){
        if(q.size()>1)flag=1; //如果队列中有多个可选点,那么排序就不能唯一确定
        int t=q.front();q.pop();
        ans[cnt++]=t;
        for(int i=0;i<n;i++){
            if(g[t][i]){
                inq[i]--;
                if(!inq[i])q.push(i);
            }
        }
    }
    if(cnt!=n)return 0; //有环
    if(!flag)return 1; //序列唯一
    return 2; //拓扑排序
}

int main()
{
    char s[10];
    while(~scanf("%d%d",&n,&m)&&(n+m)){
        memset(in,0,sizeof(in));
        memset(g,0,sizeof(g));
        int i;
        for(i=1;i<=m;i++){
            scanf("%s",s);
            in[s[2]-'A']++;
            g[s[0]-'A'][s[2]-'A']=1;
            int t=toposort();
            if(t==0){
                printf("Inconsistency found after %d relations.\n",i);
                break;
            }
            else if(t==1){
                printf("Sorted sequence determined after %d relations: ",i);
                for(int j=0;j<n;j++)printf("%c",(char)('A'+ans[j]));
                printf(".\n");break;
            }
        }
        if(i>m)printf("Sorted sequence cannot be determined.\n");
        else for(i=i+1;i<=m;i++)scanf("%s",s);
    }
    return 0;
}


posted @ 2016-07-08 19:01  HARD_UNDERSTAND  阅读(164)  评论(0编辑  收藏  举报