POJ 1094 Sorting It All Out【floyd传递闭包+拓扑排序】

Sorting It All Out

Time Limit: 1000MS

 

Memory Limit: 10000K

Total Submissions: 31994

 

Accepted: 11117

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个字母和这么些个关系,让你确定这些字母之间的关系是否会出现环,或者是找不到明确的排名关系,也或者是让你输出排名顺序。


具体分析:题干要求的是每知道一个关系,就进行一次判断,如果当前关系加入之后能够找到所有字母的排名关系,那么就输出排名关系。如果找到了矛盾的环,比如样例2一样,就输出会出现矛盾,如果整个过程没有出现矛盾或者是能够找到排名顺序,输出Sorted sequence cannot be determined.。


思路:首先分析到一共大写字母就26个,而且题目也保证了一共也就是26个点,辣么我们可以用floyd思想来搞定关系的传递闭包问题。如果i大于j,j大于k,辣么i也一定大于k。根据这样的思想,三层for搞一遍之后,我们就能得到一个当前状态的关系图。我们知道,如果一用有n个人,能够确定有a个人比自己强,有b个人比自己弱,如果a+b==n-1那么一定就能判断出我的排名位子,所以不难理解,如果所有人都有这样的关系,那么当前状态图一定是能够确定的了所有人的排名关系的。


那么因为要输出排名顺序,这个东西用floyd算法明显不能输出其具体的关系次序,所以我们这里应该想到用拓扑排序来搞定这个问题,度为0的表示当前弱者。一直拓扑下去就好。这里要注意一个点,因为拓扑排序的全序关系一定不能和传递闭包(也就是floyd之后)的图混淆,也就是说拓扑排序不能用传递闭包之后的图。因为这个全序关系是一定的,floyd之后当前图的状态变成了一个拓展图,这个时候用拓扑排序得到的结果明显也就不是该要的结果。所以我们这里维护一个基图。


搞定了这个问题,那么成环的问题呢?(矛盾的问题呢?)其实稍加思考就能明白,我们既然都已经使用floyd来递推排名关系了,我们完全可以靠这个来判断是否成环了啊。

如果floyd之后map【i】【i】==1.那么就说明矛盾了呗。


所以我们整体的思路就是这样的:每一次入一条边,先floyd一下,首先判断有没有环,如果没有继续判断,是否当前状态下的拓展图(floyd递推排名关系之后的图)是否能够满足找到所有点的a和b使得a+b==n-1。如果全部的点的a+b都等于了n-1,辣么也就说明当前图一定能够找到排名关系了,这个时候,我们只需要来一次拓扑排序并记录一下拓扑过程中每一次找到的度为0的点,然后输出即可。如果整个过程没有环,也找不到排名关系,辣么输出Sorted sequence cannot be determined.即可。


注意的点:输出的时候千万不要少了一个句号。注意所有数组memset。


AC代码:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct path
{
    int x,y;
}a[121222];
int map[50][50];
int ans[50];
int map2[50][50];
int vis[50];
int n,m;
int degree[50];
int  floyd(int num)
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            map2[i][j]=map[i][j];
        }
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            for(int k=0;k<n;k++)
            {
                if(map2[j][i]==1&&map2[i][k]==1)
                {
                    map2[j][k]=1;
                }
            }
        }
    }
    for(int i=0;i<n;i++)
    {
        if(map2[i][i]==1)return -1;
    }
    int relation[50];
    memset(relation,0,sizeof(relation));
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(map2[i][j]==1)
            {
                relation[j]++;
                relation[i]++;
            }
        }
    }
    int i;
    for(i=0;i<n;i++)
    {
        if(relation[i]!=n-1)break;
    }
    if(i==n)return 1;
    return 0;
}
void solve(int num)
{
    memset(vis,0,sizeof(vis));
    queue<int >s;
    int cont=0;
    for(int i=0;i<n;i++)
    {
        if(degree[i]==0)
        {
            s.push(i);
            vis[i]=1;
            ans[cont++]=i;
        }
    }
    while(!s.empty())
    {
        int u=s.front();
        s.pop();
        for(int j=0;j<n;j++)
        {
            if(map[u][j]==1&&vis[j]==0)
            {
                degree[j]--;
                if(degree[j]==0)
                {
                    s.push(j);
                    ans[cont++]=j;
                    vis[j]=1;
                }
            }
        }
    }
    printf("Sorted sequence determined after %d relations: ",num+1);
    for(int i=0;i<cont;i++)
    {
        printf("%c",ans[i]+'A');
    }
    printf(".\n");
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)break;
        memset(map2,0,sizeof(map2));
        memset(degree,0,sizeof(degree));
        memset(map,0,sizeof(map));
        for(int i=0;i<m;i++)
        {
            char tmp[10];
            scanf("%s",tmp);
            int u=tmp[0]-'A';
            int v=tmp[2]-'A';
            a[i].x=u;
            a[i].y=v;
        }
        int i;
        for(i=0;i<m;i++)
        {
            int u=a[i].x;int v=a[i].y;
            map[u][v]=1;
            degree[v]++;
            int tmp=floyd(i);
            if(tmp==-1)
            {
                printf("Inconsistency found after %d relations.\n",i+1);
                break;
            }
            if(tmp==1)
            {
                solve(i);
                break;
            }
        }
        if(i==m)
        {
            printf("Sorted sequence cannot be determined.\n");
        }
    }
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值