This is a problem given in the Graduate Entrance Exam in 2018: Which of the following is NOT a topological order obtained from the given directed graph? Now you are supposed to write a program to test each of the options.
Input Specification:
Each input file contains one test case. For each case, the first line gives two positive integers N (≤ 1,000), the number of vertices in the graph, and M (≤ 10,000), the number of directed edges. Then M lines follow, each gives the start and the end vertices of an edge. The vertices are numbered from 1 to N. After the graph, there is another positive integer K (≤ 100). Then K lines of query follow, each gives a permutation of all the vertices. All the numbers in a line are separated by a space.
Output Specification:
Print in a line all the indices of queries which correspond to "NOT a topological order". The indices start from zero. All the numbers are separated by a space, and there must no extra space at the beginning or the end of the line. It is graranteed that there is at least one answer.
Sample Input:
6 8
1 2
1 3
5 2
5 4
2 3
2 6
3 4
6 4
6
5 2 3 6 4 1
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
Sample Output:
0 4 5
题意分析:
这道题是有关拓扑排序,可以理解为就是按入度从小到大一个个取出节点,每取出一个节点,他对应的邻接表的所有节点的入度都要-1
在这道题中反了一下,是先知道序列再判断是否是拓扑排序,就转换为当前节点的入度是否要大于上一个节点,判断完了之后从队列中移除,并且移除节点的邻接表里的所有节点都要入度-1
这道题在写的时候要注意数组或者vector的传值问题,一开始值传递,地址传递没有搞清楚导致一直没法AC
代码如下:
2022.06.04:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m,k,v1,v2,a,flag=0,in[1010];
cin>>n>>m;
vector<int> v[1010];
for(int i=1;i<=m;i++)
{
cin>>v1>>v2;
v[v1].push_back(v2);
in[v2]++;//入度
}
cin>>k;
for(int i=0;i<k;i++)
{
int judge=1;
vector<int> tin(in,in+n+1);
for(int j=0;j<n;j++){
cin>>a;
if(tin[a]!=0)judge=0;//入度不为0,不是拓扑序列,还不能输出
for(int it:v[a])tin[it]--;//每次选中某个点后要将它所指向的所有结点的入度-1
}
if(judge==1)continue;
printf("%s%d",flag==1?" ":"",i);
flag=1;
}
cout<<endl;
return 0;
}
2022.08.10:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1010;
int n, m, k;//n个点,m条边,k个问题
vector<int> G[MAXN];//邻接表
int inDegree[MAXN] = { 0 };//每个节点的入度
bool isTopologicalSort(queue<int> q, vector<int> inDegree)
{
//判断后一个的入度是否>=前一个的
//每判断一个就将其出局,与它相连的那个节点的入度就-1
int last = q.front();
for (int i = 0; i < G[last].size(); i++) {
inDegree[G[last][i]]--;
}
q.pop();
while (!q.empty()) {
int curr = q.front();
if (inDegree[curr] >= inDegree[last]) {
for (int i = 0; i < G[curr].size(); i++) {
inDegree[G[curr][i]]--;
}
q.pop();
last = curr;
}
else return false;
}
return true;
}
int main()
{
cin >> n >> m;
int v1, v2;
for (int i = 0; i < m; i++) {
cin >> v1 >> v2;
inDegree[v2]++;
G[v1].push_back(v2);
}
cin >> k;
bool isfirst = true;
for (int i = 0; i < k; i++) {
int t;
queue<int> q;
for (int j = 0; j < n; j++) {
cin >> t;
q.push(t);
}
vector<int> ind(n + 1);
for (int k = 1; k <= n; k++) {
ind[k] = inDegree[k];
}
if (!isTopologicalSort(q, ind)) {
if (!isfirst)cout << " " << i;
else {
isfirst = false;
cout << i;
}
}
}
return 0;
}
运行结果如下:
2022.06.04:
2022.08.10: