【POJ1094】【VIJOS3014】变量排序

 

【问题描述】

把不同的变量进行升序排序用小于操作符命令实现的。例如由A < B, B < C 和 C < D 可以得到升序序列A, B, C, D 。

在本题中,你将得到若干条小于操作符命令,形如A < B 的格式,请你确定利用这些命令,能否得到一个唯一的升序序列。  

 

【输入格式】         

  第1行为整数n,m,n(2 <= n<= 26)表示参与排序的是前n个大写字母,m表示给出命令的条数。

   

【输出格式】         

输出一行:如果根据输入能得到唯一的升序序列,则输出“Sorted sequence determined after xxx relations: yyy...y.

如果不能得到唯一的升序序列,则输出:“Sortedsequence cannot be determined.

如果不能得到升序序列,则输出:“Inconsistencyfound after xxx relations.

上面的信息中 xxx 是一个整数,是表示至多根据前xxx条信息就可以得出该结论。 yyy...y表示得到的升序序列的大写字母串。

         

【输入样例】         

[样例1]

 4 6

 A < B

 A < C

 B < C

 C < D

 B < D

 A < B

[样例2]

 3 2

 A < B

 B < A

[样例3[

 26 1

 A < Z   

         

【输出样例】         

[样例1]

 Sorted sequencedetermined after 4 relations: ABCD.

[样例2]

 Inconsistency foundafter 2 relations.

[样例3]

 Sorted sequence cannotbe determined.  

         

【数据范围】         

2 <= n <= 26 

 

【思路梳理】

    很显然这道题是一道DAG图的拓扑排序动态规划。首先题目中涉及到了判断“至多根据前x条信息就可得出结论”,说明需要在输入的过程中同时进行处理。程序可以通过BFS或者是动态规划中的记忆化搜索实现。笔者才疏学浅,所以以下代码仅给出BFS(BoardFirst Searching)版本供参考。显然会出现3种情况,这个时候就应该考虑到对于每一条信息,BFS都应该给出一个参考值(在以下代码中:0代表存在环,即能得到0个升序排列;1代表能够得到唯一的一个升序序列;2代表能得到不唯一的升序序列)。

    首先先考虑判断环——存在0个升序序列时。很显然当出现“A<B,B<C,A>C”这样的情况时无论后来怎么处理都会始终存在一个环,所以判断环是比较容易的。出现环时,显然进入过队列的元素始终小于n(互成环的元素始终不可能将入度减少至0)。

    其次,较为容易的是判断唯一升序序列。直接按照正常的拓扑排序即可。

    最后需要考虑的是不唯一的升序序列。判断是否存在不唯一升序序列就是需要判断是否会存在某一个时刻,队列中有多个入度为0的元素等待处理。显然不可能直接在未完全给出所有信息的情况下判断出是否存在这样的时刻(举个例子:对于任意一个有三个或更多待排序的元素,当只有一条信息时,一定有不唯一的升序序列)。

    笔者将会把对细节的说明以注释的形式加入代码中。

 

【C++代码】

#include<queue>

#include<cstdio>

#include<string>

#include<cstring>

#include<sstream>

#include<iostream>

#include<algorithm>

#define maxn 30

using namespace std;

int m,n,rd[maxn],trd[maxn];

vector<int>g[maxn],topo;

 

int BFS()

{

queue<int>q;

    memcpy(trd,rd,sizeof(rd));      //因为可能需要多次用到rd(入度)数组,所以在对它进行操作时要拷贝一份至trd数组中,对trd进行操作,反复调用BFS的过程中,trd会不断被rd所覆盖。

 

    for(inti=1;i<=n;i++)if(trd[i]==0) q.push(i);//初始化队列,将所有入度为0的元素加入队列

    intflag=0;       //决定返回值,先赋初值,防止根本没有进行while循环

    topo.clear();     //应当记得将topology在BFS前清零

    while(!q.empty()) //经典拓扑排序的代码

    {

       if(q.size()>1)    flag=2;    //应当注意的是在任何时候出现过队列中存在多个元素,flag返回值都应该为2

       inti=q.front();q.pop();

       topo.push_back(i);

      

       for(intj=0;j<g[i].size();j++)

       {

           intk=g[i][j];

           if(trd[k]>0)  trd[k]--;

           if(trd[k]==0) q.push(k);

       }

    }

   

    if(topo.size()<n) return 0;

if(flag==2)   return flag;

    return1;

}

 

int main()

{

//  freopen("in.txt","r",stdin);

    cin>>n>>m;

    for(inti=1;i<=m;i++)

    {

       charstr[10];

       scanf("%s",str);

       inta=str[0]-'A'+1;

       intb=str[2]-'A'+1;

       g[a].push_back(b);

       rd[b]++;

       intt=BFS();

      

       if(t==0)

       {

           printf("Inconsistencyfound after %d relations.",i);

           break;

       }

      

       elseif(t==1)

       {

           printf("Sortedsequence determined after %d relations: ",i);

           for(intj=0;j<topo.size();j++)  printf("%c",topo[j]+'A'-1);

           printf(".");

           break;

       }

      

       elseif(t==2 && i==m)//注意要当整个for循环结束时才能够确定是否存在不唯一的升序序列,判断i是否等于m

       {

           printf("Sortedsequence cannot be determined.");

       }

    }

   

    return0;

}

 

 


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值