题解【洛谷P1347】排序
题目描述
一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列\(A,B,C,D\) 表示\(A<B,B<C,C<D\)。在这道题中,我们将给你一系列形如\(A<B\)的关系,并要求你判断是否能够根据这些关系确定这个数列的顺序。
输入格式
第一行有两个整数\(n,m\),\(n\)表示需要排序的元素数量,\(2 \leq n \leq 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
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.
题解
这是一道拓扑排序的经典题。
考虑如何建图:
我们可以将题目中给出的字符都减去\(A\),把字符映射成数字。
若\(A < B\),则从\(A\)向\(B\)连一条边。
问题就变成了一道有关拓扑排序的题目。
我们采用对图中的每个点进行标号来进行拓扑排序。
首先分类讨论一下:
- 如果是第一种情况,即根据前\(x\)个关系即可确定这\(n\)个元素的顺序,就说明图中的拓扑排序是唯一的,即图变成了一条链,最大编号为\(n\)。
- 如果是第二种情况,就是图中出现了环,即已经进行拓扑排序的点的个数小于已经确定关系的点的个数。确定关系的点就是已经在输入中出现过的点。
- 其它的就是第三种情况。
然后就应该在每次建立一条边的时候都对图进行一次拓扑排序,依次判断上面的第一种和第二种情况,判断成功了就直接结束程序。
如果所有的边都建完了还没有结束程序,就要输出第三种情况。
因为\(2 \leq n \leq 26\),所以我们可以直接按照上面的思路直接写出代码,不需要加任何优化即可\(AC\)。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <string>
#include <set>
#define itn int
#define gI gi
using namespace std;
inline int gi()
{
int f = 1, x = 0; char c = getchar();
while (c < '0'|| c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return x * f;
}
int n, m, sum, u, tot, uu, uuu, in[30], p, a[30], ins[30], c[30], vis[30];
string s;
vector <int> v[30];
set <int> qwq;
struct Node
{
int bh/*编号*/, cc/*标记拓扑排序的层数*/;
};
inline void toposort()
{
queue <Node> q; //用于拓扑排序的队列
memset(c, 0, sizeof(c));//记录答案
tot = 0;//tot要清零
for (int i = 0; i < 26; i+=1)
{
if (!ins[i] && qwq.count(i))//首先将入读为0且已经有边与它相连的点加入队列
{
q.push((Node){i, 1});//加入队列
c[++tot] = i;//记录答案
++p;//将访问到的点的个数加一
}
}
while (!q.empty())//如果队列不为空
{
int u = q.front().bh, w = q.front().cc; q.pop();//取出队首
int len = v[u].size();
for (int i = 0; i < len; i+=1)//访问边数
{
int j = v[u][i];
--ins[j];//入度减一
if (!ins[j]) //当前点的入度为0
{
++p;//多访问了一个点
q.push((Node){j, w + 1});//加入队列
sum = max(sum, w + 1);//最大层数更新
c[++tot] = j;//记录答案
}
}
}
if (sum == n)//第一种情况
{
printf("Sorted sequence determined after %d relations: ", uu);
for (int i = 1; i <= tot; i+=1) printf("%c", c[i] + 'A');//输出答案
puts(".");
exit(0);//直接结束程序
}
else if (p != uuu)//第二种情况
{
printf("Inconsistency found after %d relations.", uu);//输出是在第几步操作后出现环
exit(0);//直接结束程序
}
}
int main()
{
n = gi(), m = gi();
for (int i = 1; i <= m; i+=1)
{
cin >> s;
uu = i;
if (s[0] == s[2]) {printf("Inconsistency found after %d relations.", i); return 0;}//两个点相等一定是第二种情况
v[s[0] - 'A'].push_back(s[2] - 'A');//加边
++in[s[2] - 'A'];//入度加一
qwq.insert(s[0] - 'A'); qwq.insert(s[2] - 'A');//将已经读入过的点加入set,set用于去重
memset(c, 0, sizeof(c));//清空数组
memcpy(ins, in, sizeof(in));//入度需要再建一个备用数组,因为每次求解答案后记录入度的数组都会发生改变
uuu = qwq.size();//当前已经输入了的点数
sum = 0; p = 0;
toposort();//求解
}
puts("Sorted sequence cannot be determined.");//第三种情况
return 0;//结束
}
题解【洛谷P1347】排序的更多相关文章
- 洛谷——P1347 排序
洛谷—— P1347 排序 题目描述 一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列A,B,C,D 表示A<B,B<C,C<D.在这道题中,我们 ...
- 洛谷 P1347 排序
题目描述 一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列A,B,C,D 表示A<B,B<C,C<D.在这道题中,我们将给你一系列形如A<B ...
- 洛谷P1347 排序
这个题看到很多人写Topo排序,其实这道题第一眼看更像是一个差分约束的裸题QWQ... 令dis[x]表示x的相对大小(1是最小,n是最大),显然,对于一个关系A<B,我们有dis[A]< ...
- 洛谷 P1347 【排序】
这篇题解没有用拓补排序 (嗐 菜就直说) 个人感觉这道题拓补排序没有变种\(Floyd\)好写吧,思维难度也低一点(亲眼目睹机房dalao这道题拓补排序调了很久). 吐槽结束,开始正题~ 对于这道题为 ...
- 题解-洛谷P4229 某位歌姬的故事
题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...
- 题解-洛谷P4859 已经没有什么好害怕的了
洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...
- 题解 洛谷P5018【对称二叉树】(noip2018T4)
\(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...
- 题解 洛谷 P3396 【哈希冲突】(根号分治)
根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...
- 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)
题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...
- 题解-洛谷P4724 【模板】三维凸包
洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...
随机推荐
- dubbo的使用
dubbo现在用的也不多,基本都在用spring cloud那一套,所以不详细写这个dubbo了. 1.zookeeper的安装 2.demo示例 我们需要把提供者注册到dubbo注册中心,消费者去订 ...
- 嵊州D5T2 折纸 folding
折纸 folding [问题描述] 在非常紧张的 NOIP 考试中,有人喜欢啃指甲,有人喜欢转铅笔,有人喜欢撕 纸条,……而小 x 喜欢迷折纸. 现有一个 W * H 的矩形纸张,监考老师想知道,小 ...
- beautifulsoup4进阶学习笔记
requests库是可以找到想要的东西,基本上几行代码就搞定,但是进一步把有用的内容提取出来变成自己想要的格式来方便后续进行数据分析 正则表达式提取的话,需要一些时间成本,这个可以每天积累一点. 这里 ...
- laravel 解决 sql mode only_full_group_by
this is incompatible with sql_mode=only_full_group_by 先贴报错是这样的哦,sql 中使用到了 group by 然后这是mysql-5.7以上版本 ...
- BurpSuite 汉化版(含注册机)安装教程
1.注册机使用方法 首先需要完成java安装及环境变量配置. 打开burp-loader-keygen.jar(注册机)--点击run--license text (随意写)--然后将生成的lic ...
- [HNOI2001] 求正整数 - 背包dp,数论
对于任意输入的正整数n,请编程求出具有n个不同因子的最小正整数m. Solution (乍一看很简单却搞了好久?我真是太菜了) 根据因子个数计算公式 若 \(m = \prod p_i^{q_i}\) ...
- "换行"和"回车"的来历
\r: return 到当前行的最左边. \n: newline 向下移动一行,并不移动左右. Linux中\n表示:回车+换行: Windows中\r\n表示:回车+换行. Mac中\r表示:回车+ ...
- Node.js、npm和webpack的安装
1. 前往Node.js官网下载安装程序 2. 一路点击下一步即可 3. 测试是否安装成功 4. 配置npm在安装全局模块时的路径和缓存cache的路径 因为在执行例如npm install webp ...
- tcp与http协议 以及python的实现
htpp协议 Rquest Headers格式: 请求方法空格URL空格协议版本回车符换行符 头部字段名:值回车符换行符 ··· 头部字段名:值回车符换行符 回车符换行符 请求数据 socket网络聊 ...
- vscode中LaTeX的编写
前言 在学习\(\mathrm{\LaTeX}\)的时候尝试过很多编辑器,但都被其复古的外观或者复杂的配置劝退.并且因为本身就在使用VScode写其他的一些语言,正好借此机会也学习一下怎么用VScod ...