目的:判断序列是否是给出有向图的拓扑序列。
输入:
N <= 1000 图的节点数字
M <=10000 有向边的数量
然后给出M条有向边。
节点 1到N
K 查询数量
每个查询给出一个所有节点的序列。
输出:
在一行输出所有不是该图形拓扑序列的编号。编号从0开始。
末尾不能有空格。因此应该先记录下结果再输出。
算法:
先用邻接矩阵记录是否有边。用bool就行,边没有权值。
拓扑序列,就是根据时间顺序排列。
#include<stdio.h>
#include<vector>
using namespace std;
const int maxn = 1010;
vector<int> g[maxn];
vector<int> ans;
int N,M,K;
int main()
{
scanf("%d%d",&N,&M);
for(int i=0;i<M;i++)//存边
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
}
scanf("%d",&K);
for(int i=0;i<K;i++)
{
vector<int> sq;
vector<int> a(maxn,-1);
for(int j=0;j<N;j++)
{
int x;
scanf("%d",&x);
sq.push_back(x);
a[x] = j;//遍序号,出现的顺序。
}
int flag = 0;
for(int j=0;j<sq.size();j++)
{
int u = sq[j];
for(int k=0;k<g[u].size();k++)
{
int v = g[u][k];
if(a[v]<a[u])
{
flag = 1;
break;
}
}
if(flag ==1)
{
break;
}
}
if(flag==1)
{
ans.push_back(i);
}
}
for(int i=0;i<ans.size();i++)
{
printf("%d",ans[i]);
if(i!=ans.size()-1)
printf(" ");
}
return 0;
}
反思:没有理解拓扑排序的意思。要搞清楚答案怎么出来的再做题,不然逻辑乱了,就会出错误。
思路顺写一遍。要比乱七八糟写一遍再修补不知道哪里的错误要快得多。做重要是理清思路。
可以用入度来做。其实是一个原理。就是每访问一个点,观察它的入度是否为零,同时它出边相连的点的入度都减去1。如果某一点访问的时候入度不为0。则证明它有上一级的点在它后方的位置,所以错误。