• POJ1094 Sorting It All Out


    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 OutputSorted sequence determined after 4 relations: ABCD.

    Inconsistency found after 2 relations.
    Sorted sequence cannot be determined.

    这是翻译过的题目https://www.acwing.com/problem/content/345/

    首先要说的是题意描述不太对。如果在矛盾前能成功判断顺序则算成功,在这个前提下优先判断是否矛盾。

    
    

    这个题的核心是利用Floyd算法构造传递闭包。以1~26代表A~Z。d[i][j]=1表示i对应的字母小于j对应的字母。构造完成后,若存在变量使得d[i][j]=1且d[j][i]=1说明矛盾,如果d[i][j]与d[j][i]有且仅有一个为1说明这条关系是成立的。d[i][j]与d[j][i]都为0的话要么是i或者j对应的字母输入里根本没涉及要么最终无法确定顺序。把所有出现过的字母列出来,按照出度(出边的数目)排序,出度最大的即为最小的字母变量。举个例子:1,2,3,4,5五个数,1小于2,3,4,5,因此出度为4;2小于3,4,5;因此出度为3…依次等差递减且出度和为n(n-1)/2。

    
    

    因此可以确定整体思路:For循环每读取到一条关系,先把读取到的变量对应的数加入vector便于后续统计操作,在d数组里令d[a][b]=1(a为小的字母对应的数…),然后跑Floyd(代码在蓝书P360)。这里要注意的是:1.在Floyd里即可判断是否矛盾,如果矛盾直接return false。2.当跑Floyd时出度也会相应变化,因此要注意及时更新。

    
    

    跑完后如果矛盾直接输出相应语句,吸收掉后面的输入并结束当前TestCase,没有矛盾的话检查当前给出所有关系涉及的字母是否等于n,不等于的话必然没法判断,直接continue,等于的话说明可以判断这些关系能不能确定最终的顺序。用一个结构体存变量对应的字母和出度,遍历vector,确定出度和,如果为(n-1)*n/2则能确定,把结构体按照出度从大到小排序(注意,最大的变量的出度和根本没涉及到的变量的出度都为0,直接排序不可,因此对于每个变量,如果在vector里能找到,则将其出度+1)。输出后吸收掉剩下的输入。如果不能确定的话根据矛盾与否输出对应的语句。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <cmath>
    using namespace std;
    int n,m;
    struct node
    {
        int num;//存字母编号
        int out;//存出度 
    };
    bool floyd(bool d[27][27],struct node nod[])//如果有矛盾 return false; 
    {
        int i,j,k;
        for(k=1;k<=26;k++)
        {
            for(i=1;i<=26;i++)
            {
                for(j=1;j<=26;j++)
                {
                    /////floyd也要更新出度 dp时出度会变化 
                    d[i][j]|=d[i][k]&d[k][j];    
                    if(i!=j&&d[i][j]==1&&d[j][i]==1)return false;
                }
            }
        }    
        for(i=1;i<=26;i++)//更新出度 
        {
            int cnt=0;
            for(j=1;j<=26;j++)
            {
                if(d[i][j])cnt++;
            }
            nod[i].out=cnt;
        }
        return true;
    }
    bool cmp(node a,node b)
    {
        return a.out>b.out;
    }
    int main()
    {
        while(scanf("%d%d",&n,&m)&&n&&m)
        {
            int i;
            bool d[27][27]={0};
            bool vis[27]={0};
            int tot_vis=0;//涉及到的变量的个数 
            int contradict=0;//判断是否矛盾的变量 
            int sure=0; //判断能否确定顺序的变量 
            struct node nod[28];//方便输出排序
            for(i=1;i<=26;i++)
            {
                nod[i].num=i;
                nod[i].out=0;
             }     
            vector<int>v;//存储涉及到的变量 
            for(i=1;i<=m;i++)
            {
                char temp[5];
                scanf("%s",temp);
                int a=temp[0]-'A'+1,b=temp[2]-'A'+1;
                if(!vis[a])
                {
                    vis[a]=1;tot_vis++;v.push_back(a);
                }
                if(!vis[b])
                {
                    vis[b]=1;tot_vis++;v.push_back(b);
                }
                d[a][b]=1;//传递的是小于关系 
                nod[a].out++;//出度++    //注意 在floyd时也要更新出度 
                bool pd=floyd(d,nod);
                if(!pd)
                {
                    contradict=i;
                    int z;
                    for(z=i+1;z<=m;z++)//吸收剩下的 
                    {
                        char s[5];
                        scanf("%s",s);
                    }
                    break;
                }
                //当前这一遍如果没有矛盾 判断能否确定关系
                if(tot_vis!=n)//字母都没出现全,肯定没法判断
                {
                    continue; 
                }
                else
                {
                    int q,w;
                    int cnt=0;
                    for(q=0;q<v.size();q++)
                    {
                        for(w=0;w<v.size();w++)
                        {
                            if(q!=w&&(d[v[q]][v[w]]==1&&d[v[w]][v[q]]==0))cnt++;
                        }
                    }
                    if(cnt==v.size()*(v.size()-1)/2)//能确定 
                    {
                        sure=i;//标记确定 把sure变量赋值为第i次确定 
                        int z;
                        for(z=i+1;z<=m;z++)//吸收剩下的 
                        {
                            char s[5];
                            scanf("%s",s);
                        }
                        break;
                    }
                    else//不能确定 
                    {
                        continue;
                    } 
                 } 
            }
            if(sure)//能确定
            {
                printf("Sorted sequence determined after %d relations: ",sure);
                int z; 
                //输出序列  注意最后一个的出度为0 会和其他没出现过的字母混杂在一起 所以加一再排序
                vector<int>::iterator it;
                 for(z=1;z<=n;z++)
                 {
                     if((it=std::find(v.begin(),v.end(),nod[z].num))!=v.end())nod[z].out++;
                 }
                sort(nod+1,nod+26+1,cmp);
                for(z=1;z<=n;z++)putchar('A'+nod[z].num-1);
                putchar('.');//不要忘记句点 
                cout<<endl;     
            } 
            else
            {
                if(contradict)
                {
                    printf("Inconsistency found after %d relations.
    ",contradict);
                 } 
                //if(contradict==0&&tot_vis!=n)//不矛盾且推断不出 
                else
                {
                    cout<<"Sorted sequence cannot be determined."<<endl;
                }    
            }
        }    
    }
    
    
  • 相关阅读:
    oracle 锁查询
    ORACLE 本session产生的redo
    UML
    面向对象
    设计思维
    程序员习惯
    程序员修炼之道
    架构指南
    微服务架构
    测试用例
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/12299954.html
Copyright © 2020-2023  润新知