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

Sorting It All Out
点击打开题目链接
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 27599 Accepted: 9557

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.

Source

East Central North America 2001

题目大意:
第一行给出两个数,n,m;n代表共有n个字母且为字典序的前n个字母,m表示下面有m个条件
然后是m行,每行三个字符,一个大写字母,然后一个‘<’字符,然后又一个大写字母;可以将这看成有向边<x,y>;
如果填入有向边后发现形成环路,则发现不一致,输出“Inconsistency found after xxx relations.”其中xxx表示已经处理的关系数;
如果填入有向边后发现n各节点构成了拓扑序列则拓扑排序成功,输出“Sorted sequence determined after xxx relations: yyy.”其中xxx同上,yyy表示按照升序已经排好了的序列
如果把所有的边填完后,发现还没有构成拓扑序列,则输出“Sorted sequence cannot be determined.”


基本思路:
                    用邻接矩阵来储存有向图map[i,j]==1表示i有到j的一条边,map[i,j]==0,则表示i到j没有边;
                  输入m条条件:
                    如果未形成拓扑序列:
                                              判断是否能出现回路(即出现环),如果出现则知矛盾,输出对应的句子,并且将排序的标志量置为假;
                                             否则,添加有向边,map[x][y]=1,入度加一,degree[y]++;
                                                            然后找入度为0的节点,并保存到q数组中,如果仅有一个入度为0的节点(tot==0)
                                                                               {
                                                                                                  将排序结束标志置为true;
                                                                                      使用删边法进行拓扑排序并记录新产生的入度为0的节点的个数tmp,如果tmp>1,则表示排序还没结束,令结束标志finish置    为false;
                                                                                   如果结束标志为true:
                                                                                               输出排序成功的句子,然后将入度还原为原来的值(删边法过程中已经将入度改变了)
                                                                                }
                             最后在判断如果m条句子都处理完了,仍未构成拓扑序列,则输出不能排序的句子;
代码:
#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int map[27][27];
int n;
int degree[27];
int go[27];
void DFS(int x)//DFS遍历x所能到达的节点
{
    int i;
    go[x]=true;
    for(i=0; i<n; i++)
        if(map[x][i]&&!go[i])
            DFS(i);
}
int main()
{
    int m;
    bool flag;
    int i,x,y,j;
    char a,b,c;
    while(~scanf("%d%d",&n,&m)&&(n||m))
    {
        flag=true;
        memset(map,0,sizeof(map[0])*27);
        memset(degree,0,sizeof(degree));
        memset(go,1,sizeof(go));
        for(i=1; i<=m; i++)
        {
            getchar();
            scanf("%c%c%c",&a,&c,&b);
            x=a-'A';
            y=b-'A';
            for(j=0; j<n; j++) go[j]=0;
            if(flag)
            {
                DFS(y);
                if(go[x])//如果y可以到达x,则说明存在环路
                {
                    printf("Inconsistency found after %d relations.\n",i);
                    flag=false;
                    continue;
                }
                map[x][y]=1;//添加有向边
                degree[y]++;//入度加一
                int tot=0;
                int q[27];
                for(int k=0; k<n&&tot<=1; k++)//找出入度为0的节点并记录下来
                    if(degree[k]==0)
                        q[++tot]=k;
                if(tot==1)
                {
                    bool finish=true;
                    while(tot<n)
                    {
                        int xx=q[tot],tmp=0;
                        for(int k=0; k<n; k++)
                            if(map[xx][k]==1&&(degree[k]-=1)==0)//将入度减一并判断是否入度为零
                            {
                                q[++tot]=k;
                                ++tmp;//记录新产生的入度为零的节点个数
                            }
                        if(tmp>1)
                        {
                            finish=false;
                            break;
                        }
                    }
                    if(finish&&tot==n)//拓扑完成
                    {
                        printf("Sorted sequence determined after %d relations: ",i);
                        for(int k=1; k<=n; k++)
                            printf("%c",'A'+q[k]);
                        printf(".\n");
                        flag=false;
                    }
                    memset(degree,0,sizeof(degree));
                    for(int j=0; j<n; j++)//还原入度
                    {
                        for(int k=0; k<n; k++)
                            if(map[j][k]==1)
                            degree[k]++;//map[j][k];
                    }
                }
            }
        }
        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、付费专栏及课程。

余额充值