P1347 排序

codevs—— P1347 排序

题目描述

一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列A,B,C,D 表示A<B,B<C,C<D。在这道题中,我们将给你一系列形如A<B的关系,并要求你判断是否能够根据这些关系确定这个数列的顺序。

输入输出格式

输入格式:

第一行有两个整数n,m,n表示需要排序的元素数量,2<=n<=26,第1到n个元素将用大写的A,B,C,D....表示。m表示将给出的形如A<B的关系的数量。

接下来有m行,每行有3个字符,分别为一个大写字母,一个<符号,一个大写字母,表示两个元素之间的关系。

输出格式:

若根据前x个关系即可确定这n个元素的顺序yyy..y(如ABC),输出

Sorted sequence determined after xxx relations: yyy...y.

若根据前x个关系即发现存在矛盾(如A<B,B<C,C<A),输出

Inconsistency found after 2 relations.

若根据这m个关系无法确定这n个元素的顺序,输出

Sorted sequence cannot be determined.

(提示:确定n个元素的顺序后即可结束程序,可以不用考虑确定顺序之后出现矛盾的情况)

输入输出样例

输入样例#1:

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:

1:
Sorted sequence determined after 4 relations: ABCD.
2:
Inconsistency found after 2 relations.
3:
Sorted sequence cannot be determined.

思路:这个题显然使用拓扑排序做。

注意:输入一个字符需要加&但是输入一个字符串不需要加&;代码:
#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 110
using namespace std;
int a,b,n,m,s,sum,tot,head[N],in[N],inn[N],p[N];
bool v,unpd,vis[N];
queue<int>q;
char ch;
int read()//在这里我用的读入优化
{
    int x=0,f=1; char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘) {x=x*10+ch-‘0‘;ch=getchar();}
    return f*x;
}
struct Edge
{
    int from,to,next;
}edge[N];
int add(int x,int y)
{
    tot++;
    edge[tot].to=y;
    edge[tot].next=head[x];
    head[x]=tot;
}//和以前的拓扑排序过程一样,只是多加了几种情况
int tp()
{
    unpd=false;    v=false; sum=0;//初始数值
    for(int i=1;i<=26;i++)//开始找入读为一的点
     {
         inn[i]=in[i];//由于我们要没输入一组后就对该序列进行判断,所以我们新设一个数组inn储存in中的各点入度的值,防止我们下一次在用时,该店的入度值已不是初始值
         if(!inn[i]&&vis[i])//该点的入读为0并且我们输入过该值
          {
              if(!v) v=true;//我们要判断有几个入读为0的点,由于如果有两个入读为0的点我们则无法判断他们的关系因为入读为0的点一定是小的,但这两个值得大小我们又无法判断
              else unpd=true;//unpd用来判断无法判段的情况
              q.push(i);
              p[++sum]=i;
           }
      }
    if(q.empty()) return 1;//如果q数组为空,就说明出现了环,则是存在矛盾的情况。
    while(!q.empty())//单纯的拓扑排序,但我们要在里面多加一点东西:和前面判断入读为0的方法一样,如果删除一个点以后出现了两个入度为0的边,这样我们将无法判断这两个点的大小
    {
        int x=q.front();v=false;q.pop();
        for(int i=head[x];i;i=edge[i].next)
        {
            inn[edge[i].to]--;
            if(!inn[edge[i].to])
            {
                q.push(edge[i].to);
                if(!v) v=true;
                else unpd=true;
                p[++sum]=edge[i].to;
            }
        }
    }
    if(sum!=s) return 1;//说明出现了环。
    if(unpd) return 2;
    return 0;
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=m;i++)
    {
        cin>>ch,a=ch-64;if(!vis[a]) vis[a]=true,s++;//s是用来存我们输入的元素的个数,方便后面判断s值与sum值的关系(来判断是否为环)
        cin>>ch;//这个在输入时其实我们也可以用一个数组来表示,在这里我们由于有一个<是没有用的,所以我们直接输入就好了
        cin>>ch,b=ch-64;if(!vis[b]) vis[b]=true,s++;//vis用来表示该数有值
        add(a,b);//在这里我们将我们输入的字符转化成了数字,方便后面进行操作
        in[b]++;//储存入读
        if(tp()==1) //在这里我们必须让他等于1,因为我们在tp函数中返回的是0,1,2
        {
            printf("Inconsistency found after %d relations.",i);//存在矛盾
            return 0;
        }
        if(sum==n&&!tp())//sum=n,说明该序列中所有的数都进行了排序,都能确定他们的位置
        {
            printf("Sorted sequence determined after %d relations: ",i);
            for(int j=1;j<=n;j++) printf("%c",p[j]+64);//在最开始的时候我竟然让他输出p[i]+64.这告诉我们要注意我们循环使用的变量i,j
            printf(".");
            return 0;
        }
    }
    printf("Sorted sequence cannot be determined.");//由于我们在tp函数中只有三种情况,除了前两种剩下的就是这一种了。
    return 0;
}

 
 
时间: 2024-08-06 03:38:04

P1347 排序的相关文章

洛谷 P1347 排序

https://www.luogu.org/problem/show?pid=1347 题目描述 一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列A,B,C,D 表示A<B,B<C,C<D.在这道题中,我们将给你一系列形如A<B的关系,并要求你判断是否能够根据这些关系确定这个数列的顺序. 输入输出格式 输入格式: 第一行有两个整数n,m,n表示需要排序的元素数量,2<=n<=26,第1到n个元素将用大写的A,B,C,D....表示.m

luogu P1347 排序

题目描述 一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列A,B,C,D 表示A<B,B<C,C<D.在这道题中,我们将给你一系列形如A<B的关系,并要求你判断是否能够根据这些关系确定这个数列的顺序. 输入输出格式 输入格式: 第一行有两个整数n,m,n表示需要排序的元素数量,2<=n<=26,第1到n个元素将用大写的A,B,C,D....表示.m表示将给出的形如A<B的关系的数量. 接下来有m行,每行有3个字符,分别为一个大写

P1347 排序(拓扑排序)

这个题是我照着题解一点点理解一点点打出来的. 拓扑排序: 定义:将有向图中的顶点以线性方式进行排序.即对于任何连接自顶点u到顶点v的有向边uv,在最后的排序结果中,顶点u总是在顶点v的前面. 确定一个图的拓扑排序是基于bfs的,bfs是基于队列的. 首先记录所有的点和所有点的入度(在连边时顺便求得的入度), if(vis[aa]!=1) vis[aa]=1,tot++;//tot记录的是目前能算得上点(因为是随读随做) if(vis[cc]!=1) vis[cc]=1,tot++; son[aa

拓扑相关题目

有关拓扑一个挺直观的图: 1.luogu P1347 排序 直通 思路: 题目中明确的提到:确定n个元素的顺序后即可结束程序,可以不用考虑确定顺序之后出现矛盾的情况. 所以我们可以每读入一个条件,就进行一遍Floyd,判断顺序的条件就是: 枚举i,然后用map数组记录一下比i要大的个数,如果n-sum==s+1(s+1的原因是因为我们是从0开始计数的),那么就用一个q数组记录下来 而如果在给出的n之内,只要有一个没有被确定,我们就不能够说已经排好序了 还有一点需要注意的是: · 如果出现了map

经典排序算法 - 冒泡排序Bubble sort

 原文出自于 http://www.cnblogs.com/kkun/archive/2011/11/23/bubble_sort.html 经典排序算法 - 冒泡排序Bubble sort 原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 这样一趟过去后,最大或最小的数字被交换到了最后一位, 然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子 例子为从小到大排序, 原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 | 第一趟排序(外循环) 第

算法 希尔排序

希尔排序 Shell Sort 介绍: 希尔排序(Shell Sort)也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本. 该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个"增量"的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序.因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率比直接插入排序有较大提高. 执行流程: 首先

算法 排序NB二人组 堆排序 归并排序

参考博客:基于python的七种经典排序算法     常用排序算法总结(一) 序前传 - 树与二叉树 树是一种很常见的非线性的数据结构,称为树形结构,简称树.所谓数据结构就是一组数据的集合连同它们的储存关系和对它们的操作方法.树形结构就像自然界的一颗树的构造一样,有一个根和若干个树枝和树叶.根或主干是第一层的,从主干长出的分枝是第二层的,一层一层直到最后,末端的没有分支的结点叫做叶子,所以树形结构是一个层次结构.在<数据结构>中,则用人类的血统关系来命名,一个结点的分枝叫做该结点的"

数字在排序数组中出现的次数

题目:统计一个数字在排序数组中出现的次数.例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4. 程序实现: import java.util.Scanner; public class Test38 { public static void main(String[] args) { /**  * 初始化数组,测试数据可以多种途径初始化  */   Scanner in = new Scanner(System.in); /*int[] a = 

算法 排序lowB三人组 冒泡排序 选择排序 插入排序

参考博客:基于python的七种经典排序算法   [经典排序算法][集锦]     经典排序算法及python实现 首先明确,算法的实质 是 列表排序.具体就是操作的列表,将无序列表变成有序列表! 一.排序的基本概念和分类 所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作.排序算法,就是如何使得记录按照要求排列的方法. 排序的稳定性: 经过某种排序后,如果两个记录序号同等,且两者在原无序记录中的先后秩序依然保持不变,则称所使用的排序方法是稳定的,反之是不稳定