拓扑排序的性质大约是:
- 在未加入拓扑排序序列的顶点中,入度为0的顶点全都属于拓扑排序序列,在入度为0的顶点加入拓扑序列后,要删去从它出去的边使得其邻接点的入度-1,这样就会产生新的入度为0的顶点了。
所以这题其实就是一道模拟,模拟拓扑排序的过程,因为拓扑排序时,每次加入序列的都是入度为0的顶点,所以只需按照给定的拓扑排序序列的顺序模拟拓扑排序:
- 如果遍历发现给定序列中的顶点的入度为0,那就模拟删边使得当前顶点的所有邻接点的入度-1;若不是0,那说明给定序列不是拓扑序列。
所以解法就是:顺序遍历要检验的序列,跟着序列的顺序判断当前顶点入度是否为0,为0就说明其确实在拓扑序列中,于是使得其邻接点的入度-1;不为0说明当前序列不是拓扑序列,不需要再判断其他的顶点了。
邻接表
# include <iostream>
# include <vector>
# include <queue>
# include <algorithm>
using namespace std;
int N, M;
vector<int> G[1001];
vector<int> inDegree(1001);
vector<int> inDegree_copy(1001);
int main() {
cin >> N >> M;
for(int i = 0;i < M;++i){
int u, v;
cin >> u >> v;
G[u].push_back(v);
inDegree_copy[v]++;
}
int K;
cin >> K;
vector<int> indices; // 装答案
for(int i = 0;i < K;++i){
inDegree = inDegree_copy;
int flag = 1;
for(int j = 0;j < N;++j){
int query;
cin >> query;
if(flag == 0) continue; // flag=0,说明这个序列已经不是拓扑序列了,不需要再检验其他顶点了,只需完成输入即可
if(inDegree[query] == 0) // 如果入度为0,说明,query是在拓扑排序的正确位置
for(int v: G[query]) // 删掉当前顶点和其出去的边,让其邻接点的入度-1
inDegree[v]--;
else
flag = 0; // 标明是错误答案
}
if(flag == 0) indices.push_back(i);
}
for(int i = 0;i < indices.size();++i){
cout << indices[i];
i != indices.size() - 1 ? cout << " " : cout << endl;
}
return 0;
}
邻接矩阵
# include <iostream>
# include <vector>
# include <queue>
# include <algorithm>
using namespace std;
const int INF = 0xffffff;
int N, M;
bool G[1001][1001] = {false};
vector<int> inDegree(1001);
vector<int> inDegree_copy(1001);
int main() {
cin >> N >> M;
for(int i = 0;i < M;++i){
int u, v;
cin >> u >> v;
G[u][v] = true;
inDegree_copy[v]++;
}
int K;
cin >> K;
vector<int> indices; // 装答案
for(int i = 0;i < K;++i){
inDegree = inDegree_copy;
int flag = 1;
for(int j = 0;j < N;++j){
int query;
cin >> query;
if(flag == 0) continue; // flag=0,说明这个序列已经不是拓扑序列了,不需要再检验其他顶点了,只需完成输入即可
if(inDegree[query] == 0){ // 如果入度为0,说明,query是在拓扑排序的正确位置
for(int v = 1;v <= N;++v) // 删掉当前顶点和其出去的边,让其邻接点的入度-1
if(G[query][v] == true)
inDegree[v]--;
} else { // 如果入度不为0,说明query不在拓扑排序的正确位置,当前序列不是拓扑序列,标记为错误答案
// 因为这个是一个一个地输入顶点,而不是一次输入一整个检验序列,所以不能break,要循环直到本轮输入完成
flag = 0; // 标明是错误答案 // break;
}
}
if(flag == 0) indices.push_back(i);
}
for(int i = 0;i < indices.size();++i){
cout << indices[i];
if(i != indices.size() - 1)
cout << " ";
else
cout << endl;
}
return 0;
}