题目地址:
https://www.acwing.com/problem/content/description/1641/
这是
2018
2018
2018年研究生入学考试中给出的一个问题:以下哪个选项不是从给定的有向图中获得的拓扑序列?现在,请你编写一个程序来测试每个选项。
输入格式:
第一行包含两个整数
N
N
N和
M
M
M,分别表示有向图的点和边的数量。接下来
M
M
M行,每行给出一条边的起点和终点。点的编号从
1
1
1到
N
N
N。再一行包含一个整数
K
K
K,表示询问次数。接下来
K
K
K行,每行包含一个所有点的排列。一行中的数字用空格隔开。
输出格式:
在一行中输出所有不是拓扑序列的询问序列的编号。询问序列编号从
0
0
0开始。行首和行尾不得有多余空格,保证存在至少一个解。
数据范围:
1
≤
N
≤
1000
1≤N≤1000
1≤N≤1000
1
≤
M
≤
10000
1≤M≤10000
1≤M≤10000
1
≤
K
≤
100
1≤K≤100
1≤K≤100
直接按拓扑排序定义验证即可。代码如下:
#include <iostream>
using namespace std;
const int N = 1010, M = 10010;
int n, m, k;
struct Edge {
int a, b;
} e[M];
int id[N];
int res[110], cnt;
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++)
scanf("%d%d", &e[i].a, &e[i].b);
scanf("%d", &k);
for (int c = 0; c < k; c++) {
for (int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
id[x] = i;
}
bool valid = true;
for (int i = 1; i <= m; i++)
if (id[e[i].a] > id[e[i].b]) {
valid = false;
break;
}
if (!valid) res[++cnt] = c;
}
for (int i = 1; i < cnt; i++) printf("%d ", res[i]);
printf("%d", res[cnt]);
}
预处理时间复杂度 O ( m ) O(m) O(m),每次询问时间 O ( m ) O(m) O(m),空间 O ( n ) O(n) O(n)。