输入样例:
6 8
1 2
1 3
5 2
5 4
2 3
2 6
3 4
6 4
5
1 5 2 3 6 4
5 1 2 6 3 4
5 1 2 3 6 4
5 2 1 6 3 4
1 2 3 4 5 6
输出样例:
3 4
算法思路:
拓扑序列是在有向无环图中的任意一条边的两点,在序列中始终是从前指向后的。所以在判断拓扑序列时,只需要遍历所有的边,检查是否在序列中满足从前指向后。
由于拓扑序列的最开始的顶点入度一定为0,也可以检查序列的入度情况,并将以该顶点的出度为入度的顶点入度减去,判断序列的入度是否始终未为0。
Java代码:(判断所有边的方向)
import java.io.*;
import java.util.ArrayList;
public class Main {
static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static int ini() throws IOException {
st.nextToken();
return (int)st.nval;
}
static class Node{
int a, b;
public Node(int a, int b) {
this.a = a;
this.b = b;
}
}
public static void main(String[] args) throws IOException {
int n = ini(), m = ini();
Node []node = new Node[m];
for(int i = 0; i < m; i++)
node[i] = new Node(ini(), ini());
int q = ini();
int []p = new int[n + 1];
int []arr = new int[n];
ArrayList<Integer> ans = new ArrayList<>();
for(int i = 0; i < q; i++) {
for(int j = 0; j < n; j++) {
arr[j] = ini();
p[arr[j]] = j; // 哈希序列中的点的位置
}
int j = 0;
for(j = 0; j < m; j++)
if(p[node[j].a] > p[node[j].b])
break;
if(j != m) ans.add(i);
}
System.out.print(ans.get(0));
for(int i = 1; i < ans.size(); i++) System.out.print(" " + ans.get(i));
}
}
Java代码:(判断入度)
import java.io.*;
import java.util.*;
public class Main1639 {
static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static int ini() throws IOException {
st.nextToken();
return (int)st.nval;
}
static int n, m, N = 1005, M = 10005, idx;
static int[]e = new int[M];
static int[]ne = new int[M];
static int[]h = new int[N];
public static void main(String[] args) throws IOException {
n = ini();
m = ini();
int[]d = new int[n + 1];
Arrays.fill(h, -1);
while(m-- > 0) {
int a = ini(), b = ini();
add(a, b);
d[b]++;
}
int q = ini();
int []arr = new int[n + 1];
int []bd = new int[n + 1];
ArrayList<Integer> ans = new ArrayList<>();
for(int p = 0; p < q; p++) {
bd = Arrays.copyOf(d, n + 1); // 先将图的入度数组备份
for(int i = 1; i <= n; i++) arr[i] = ini();
for(int i = 1; i <= n; i++) {
int t = arr[i];
if(bd[t] == 0) { // 入度为0顶点
for(int j = h[t]; j != -1; j = ne[j]) {
int k = e[j]; // 该顶点的邻接边
bd[k]--; // 入度减一
}
}else {
ans.add(p); // 遍历到不满足入度为0时为不合法情况
break;
}
}
}
System.out.print(ans.get(0));
for(int i = 1; i < ans.size(); i++) System.out.print(" " + ans.get(i));
}
public static void add(int a, int b) {
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
}