[luogu p1347] 排序
排序
题目描述
一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列 \(A,B,C,D\) 表示\(A<B,B<C,B<D\)。在这道题中,我们将给你一系列形如 \(A < B\) 的关系,并要求你判断是否能够根据这些关系确定这个数列的顺序。
输入输出格式
输入格式
第一行有两个正整数 \(n,m\),\(n\) 表示需要排序的元素数量,\(2\leq n\leq 26\),第 \(1\) 到 \(n\) 个元素将用大写的 \(A,B,C,D\dots\) 表示。\(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 \leq n \leq 26,1 \leq m \leq 600\)。
分析
给你几个先后关系,让你确定先后序列,那不就是拓扑吗!
首先来看数据范围,\(n \le 26\),说明我们可以不用担心TLE的事情了。这个范围只要不是特别暴力的,都可以过。
建好图以后,我们要进行拓扑排序。有三种情况:
- 新增此条件后仍不能确定:两种情况
- 最开始入度为0的点不止一个,那么条件不足。 因为你无法确定这几个入度为0的点的顺序。
- 进行topsort算法核心时,如果发现取出一个点 \(u\),却push了多个点,那么条件不足。 因为这两个点都只有点 \(u\) 指向,这两个点的顺序同样无法确定。
- 条件矛盾:说明有环。
- 有环的情况下有些点的入度永远不为0,因此判断是不是所有点都入过队列了,如果不是,说明条件矛盾,如果是的,说明不矛盾。
- 如果 “新增此条件后仍不能确定”和“条件矛盾”同时满足,程序应判断为条件矛盾。 如果你判断的是新增此条件后仍不能确定,你会拿到30分的好成绩。而且如果是这个bug,样例是测不出来的。
- 确定了:如果上两条都不满足,那么显然就是确定了。
我们假设topsort函数中,如果是第一种情况,返回0;如果是第二种情况,返回-1;如果是第三种情况,返回1.
然后再观察,发现他是一条一条判断的,也就是说我们每输入一个条件,都要重置ind数组,进行一遍topsort。如果返回0,那么什么都不做,继续输入下一个条件;如果返回-1,那么直接输出矛盾,退出程序;如果返回1,那么输出已确定,退出程序。如果所有条件都输入了,程序还是没结束,说明还未确定,输出未确定。
看起来很暴力,但是实际上,\(n\le 26\) 这个数据范围,这个一点都不暴力。
上代码!
代码
/*
* @Author: crab-in-the-northeast
* @Date: 2020-09-30 19:35:47
* @Last Modified by: crab-in-the-northeast
* @Last Modified time: 2020-10-01 08:44:36
*/
#include <iostream>
#include <cstdio>
#include <climits>
#include <vector>
#include <queue>
const int maxn = CHAR_MAX;
const int maxm = 605;
std :: vector <int> G[maxn];
int ind[maxn];
int n, m;
int c_to_i(char ch) {
return ch - 'A' + 1;
}
std :: queue <int> seq;
int topsort() {
std :: queue <int> q;
bool valid = true;
for (int i = 1; i <= n; ++i)
if (ind[i] == 0) {
q.push(i);
seq.push(i);
}
if (q.size() > 1)
valid = false;
while (!q.empty()) {
bool flag = false;
int u = q.front();
q.pop();
for (int i = 0; i < G[u].size(); ++i) {
int v = G[u][i];
--ind[v];
if (ind[v] == 0) {
if (flag) valid = false;
q.push(v);
seq.push(v);
flag = true;
}
}
}
if (seq.size() != n) return -1;
if (!valid) return 0;
return 1;
}
int main() {
std :: scanf("%d %d", &n, &m);
for (int i = 1; i <= m; ++i) {
char str[5];
std :: scanf("%s", str + 1);
int u = c_to_i(str[1]), v = c_to_i(str[3]);
G[u].push_back(v);
for (int j = 1; j <= n; ++j)
ind[j] = 0;
for (int u = 1; u <= n; ++u)
for (int j = 0; j < G[u].size(); ++j)
++ind[G[u][j]];
while (!seq.empty())
seq.pop();
int res = topsort();
if (res == 1) {
std :: printf("Sorted sequence determined after %d relations: ", i);
while (!seq.empty()) {
std :: printf("%c", seq.front() + 'A' - 1);
seq.pop();
}
puts(".");
return 0;
} else if (res == -1) {
std :: printf("Inconsistency found after %d relations.\n", i);
return 0;
}
}
puts("Sorted sequence cannot be determined.");
return 0;
}