这一题是给出一个有向图<n,m>,然后给出几个排序,判断哪几个不是拓扑排序,把不是的按顺序输出来(下标从零开始)。
我用二维数组存储图,然后一个个排序遍历,判断是否存在某个元素指向在它之前被遍历的元素,如果有就不是拓扑排序。这种方法时间复杂度为
O
(
n
2
)
O(n^2)
O(n2),空间复杂度为
O
(
n
2
)
O(n^2)
O(n2),以为会超时,没想到过了。
网上查了一下,可以使用出入度来做,时间复杂度为
O
(
m
)
O(m)
O(m),空间复杂度为
O
(
n
)
O(n)
O(n)。当拓扑排序遍历到相关元素时,其之前指向它的元素都已经被遍历,即删除已遍历的元素看,当前元素的入度为0。遍历排序中的每个元素,判断其入度是否为0,不是则不是拓扑排序,是则将其指向的元素的入度都减一并重复上述过程直到结束。感觉这才是抓住本质的正确解法,也让我对拓扑排序更加了解。
#include <bits/stdc++.h>
using namespace std;
int graph[1001][1001] = {0};
int main()
{
int n,m;
scanf("%d%d",&n,&m);
int x,y;
for(int i=0;i<m;i++){
scanf("%d%d",&x,&y);
graph[x][y]=1;
}
int k;
scanf("%d",&k);
vector<int> result;
int v[1001];
for(int i=0;i<k;i++){
for(int j=0;j<n;j++){
scanf("%d",&v[j]);
}
bool notOrder = false;
for(int j=1;j<n;j++){
for(int t=0;t<j;t++){
if(graph[v[j]][v[t]]){
notOrder = true;
}
}
if(notOrder){
break;
}
}
if(notOrder){
result.push_back(i);
}
}
printf("%d",result[0]);
for(int i =1;i<result.size();i++){
printf(" %d",result[i]);
}
return 0;
}