题目大意:
给定一个有向图,N个顶点,M条边,现给定K个查询,每一个查询输入一个序列,判断该序列是否是该图的拓扑排序序列,如果不是,输出该序列的编号(从0开始)
算法思路:
模拟拓扑排序的过程,对于输入的序列,先检查其入度是否为0,不为0说明该序列不是拓扑排序序列,否则就将该结点的邻接点的入度全部减一,依次向下进行判断,直到退出循环。为了防止最后一个测试点的格式错误,所有不是拓扑排序的序列编号都使用result数组保存,最后输出结果即可。
提交结果:
AC代码:
#include<cstdio>
#include<vector>
using namespace std;
const int maxn = 1005;
int inDegree[maxn];// 每一个结点的入度
int tempInDegree[maxn];// 每次查询暂存入度数组
int query[maxn];// 每次查询的序列
vector<int> Adj[maxn];// 邻接表,保存每一个结点的所有邻接点
vector<int> result;// 保存所有不是拓扑排序序列的编号
int N,M;
bool isTopologicalOrder(){
for(int i=1;i<=N;++i){
// 重新赋值入度数组
tempInDegree[i] = inDegree[i];
}
for(int i=0;i<N;++i){
if(tempInDegree[query[i]]!=0){
return false;
}
for(auto &item:Adj[query[i]]){
// 将当前顶点的邻接点的入度减一
--tempInDegree[item];
}
}
return true;
}
int main(){
scanf("%d %d",&N,&M);
for(int i=0;i<M;++i){
int a,b;
scanf("%d %d",&a,&b);
++inDegree[b];
Adj[a].push_back(b);
}
int K;
scanf("%d",&K);
for(int i=0;i<K;++i){
for(int j=0;j<N;++j){
scanf("%d",&query[j]);
}
if(!isTopologicalOrder()){
result.push_back(i);
}
}
for(int i=0;i<result.size();++i){
printf("%d",result[i]);
if(i<result.size()-1) printf(" ");
}
return 0;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。