贤鱼的刷题日常【c++拓扑排序】P1347排序

简介: P1347排序详细题解

@TOC

题目

题目描述
一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列 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 x relations.

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

Sorted sequence cannot be determined.

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

输入输出样例
输入 #1复制
4 6
A<B
A<C
B<C
C<D
B<D
A<B
输出 #1复制
Sorted sequence determined after 4 relations: ABCD.
输入 #2复制
3 2
A<B
B<A
输出 #2复制
Inconsistency found after 2 relations.
输入 #3复制
26 1
A<Z
输出 #3复制
Sorted sequence cannot be determined.
说明/提示
2≤n≤26,1≤m≤600。

思路

考虑到题目的特殊,有可能不需要全部关系就可以排序出全部字母顺序,所以这道题需要边输入边处理,并且题目中说过,如果存在缺少条件并且关系矛的情况下输出条件矛盾(Inconsistency found after x relations.),所以缺少条件的情况放在最后处理,如果条件矛盾直接输出即可,那么题目就明朗了:

AC代码

#include<cmath>
#include<queue>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int cnt;
struct edge{
    int u,v,next;
}e[10005];
int du[100006];
int ecnt=0;
int head[100006];
void add(int u,int v){
    e[++ecnt].v=v;
    e[ecnt].u=u;
    e[ecnt].next=head[u];
    head[u]=ecnt;
}
int ans[10005];
int n,m;
char b[1005];
int fg=0;
int tp(){
    fg=0;
    queue<int>q;
    int c=0;
    for(int i=1;i<=n;i++){
        if(!du[i]){
            q.push(i);
            c++;//记录入度为0的点,也就是一开始的起点
        }
    }
    if(c==0){//没有入度为0说明这道题的条件让点成环了,就好比A>B,B>A;所以直接直接结束判断并且在主函数内输出
        return -1;
    }else if(c>1){//如果入度为0的点不止一个,就说明缺少条件,比如A>D,C>D这种,但是考虑到题目说缺少条件和矛盾的情况下输出矛盾,所以先记录下在函数结尾处判断
        c=-1;
    }
    cnt=0;
    while(!q.empty()){
        int x=q.front();
        q.pop();//出队并且在下方记录答案
        int tmp=0;
        ans[++cnt]=x;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].v;
            du[v]--;
            if(!du[v]){//如果有入度为0的点就入队
                q.push(v);
                tmp++;
            }
            if(du[v]<0){//如果有个点的入度小于0了就说明条件矛盾了,直接输出
                return -1;
            }
        }
        if(tmp>1) c=-1;//如果一次多个点入度为0说明可能缺少条件了
    }
    if(cnt!=n) return -1;//如果记录答案的点数和输入的n不同说明条件矛盾了
    if(c==-1) return 0;//条件不矛盾的情况下少条件就返回0
    return 1;//可以完成返回1
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        char a;
        scanf(" %c<%c",&a,&b[i]);//这里只需要知道入度的点,所以数组记录v就可以了
        add(a-'A'+1,b[i]-'A'+1);
        memset(du,0,sizeof(du));
        memset(ans,0,sizeof(ans));//因为多次处理,所以数组必须清空
        for(int j=1;j<=i;j++) du[b[j]-'A'+1]++;//每次都要入度处理
        int f=tp();
        if(f==1){//从这里按照题目要求输出就好
            cout<<"Sorted sequence determined after "<<i<<" relations: ";
            for(int k=1;k<=n;k++){//边输入边判断可以方便得知在那一步完成题目要求
                cout<<(char)(ans[k]+'A'-1);
            }
            cout<<".";//不要忘记这玩意
            return 0;
        }
        else if(f==-1){
            cout<<"Inconsistency found after "<<i<<" relations.";
            return 0;
        }

    }
    cout<<"Sorted sequence cannot be determined.";//最后判断缺少条件的情况

}

制作不易关注一下吧^^

相关文章
|
8月前
|
人工智能 算法 测试技术
【数学】【排序】【C++算法】3027人员站位的方案数
【数学】【排序】【C++算法】3027人员站位的方案数
|
15天前
|
存储 人工智能 算法
【C++数据结构——内排序】二路归并排序(头歌实践教学平台习题)【合集】
本关任务是实现二路归并算法,即将两个有序数组合并为一个有序数组。主要内容包括: - **任务描述**:实现二路归并算法。 - **相关知识**: - 二路归并算法的基本概念。 - 算法步骤:通过比较两个有序数组的元素,依次将较小的元素放入新数组中。 - 代码示例(以 C++ 为例)。 - 时间复杂度为 O(m+n),空间复杂度为 O(m+n)。 - **测试说明**:平台会对你编写的代码进行测试,提供输入和输出示例。 - **通关代码**:提供了完整的 C++ 实现代码。 - **测试结果**:展示代码运行后的排序结果。 开始你的任务吧,祝你成功!
32 10
|
15天前
|
搜索推荐 算法 数据处理
【C++数据结构——内排序】希尔排序(头歌实践教学平台习题)【合集】
本文介绍了希尔排序算法的实现及相关知识。主要内容包括: - **任务描述**:实现希尔排序算法。 - **相关知识**: - 排序算法基础概念,如稳定性。 - 插入排序的基本思想和步骤。 - 间隔序列(增量序列)的概念及其在希尔排序中的应用。 - 算法的时间复杂度和空间复杂度分析。 - 代码实现技巧,如循环嵌套和索引计算。 - **测试说明**:提供了测试输入和输出示例,帮助验证代码正确性。 - **我的通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了代码运行的测试结果。 通过这些内容,读者可以全面了解希尔排序的原理和实现方法。
46 10
|
15天前
|
搜索推荐 C++
【C++数据结构——内排序】快速排序(头歌实践教学平台习题)【合集】
快速排序是一种高效的排序算法,基于分治策略。它的主要思想是通过选择一个基准元素(pivot),将数组划分成两部分。一部分的元素都小于等于基准元素,另一部分的元素都大于等于基准元素。然后对这两部分分别进行排序,最终使整个数组有序。(第一行是元素个数,第二行是待排序的原始关键字数据。本关任务:实现快速排序算法。开始你的任务吧,祝你成功!
33 7
|
15天前
|
存储 算法 搜索推荐
【C++面向对象——群体类和群体数据的组织】实现含排序功能的数组类(头歌实践教学平台习题)【合集】
1. **相关排序和查找算法的原理**:介绍直接插入排序、直接选择排序、冒泡排序和顺序查找的基本原理及其实现代码。 2. **C++ 类与成员函数的定义**:讲解如何定义`Array`类,包括类的声明和实现,以及成员函数的定义与调用。 3. **数组作为类的成员变量的处理**:探讨内存管理和正确访问数组元素的方法,确保在类中正确使用动态分配的数组。 4. **函数参数传递与返回值处理**:解释排序和查找函数的参数传递方式及返回值处理,确保函数功能正确实现。 通过掌握这些知识,可以顺利地将排序和查找算法封装到`Array`类中,并进行测试验证。编程要求是在右侧编辑器补充代码以实现三种排序算法
34 5
|
8月前
|
算法 搜索推荐 C++
【C++】sort()、stable_sort()和partial_sort()排序函数详解
【C++】sort()、stable_sort()和partial_sort()排序函数详解
233 0
|
7月前
|
C++ 容器
C++之deque容器(构造、赋值、大小、插入与删除、存取、排序)
C++之deque容器(构造、赋值、大小、插入与删除、存取、排序)
|
7月前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-2
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
7月前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-1
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
7月前
|
算法 搜索推荐 C++
C++之STL常用算法(遍历、查找、排序、拷贝、替换、算数生成、集合)
C++之STL常用算法(遍历、查找、排序、拷贝、替换、算数生成、集合)