一、技术总结
- 首先这一题是关于拓扑排序的,必须明确啥是拓扑排序,也就是对于有向无环图,能够生成拓扑序列;使得该序列中任意两个顶点u、v,如果存在u->v,那么在序列中u一定在v的前面。
- 然后这一题是给出一个有向无环图,要我们判断所给的序列是否为拓扑排序。
- 无论是判断是拓扑序列还是该图是否为有向无环图,都是要定义这几个变量的,也就是存储图的vector< int > v[1010]领接表,然后还需要一个存储每个结点的入度的数组int indegree[1010]。
- 如果是要判断所给序列是否为拓扑排序,设置一个judge初始为1, 就需要遍历序列中的每一个结点,按顺序进行遍历,如果有当前结点的入度不为0,judge = 0,那么说明该序列不是拓扑排序,遍历到该结点后,将该结点所能够到达的所有结点的入度都减一。遍历完后,judge判断是否为1。
判断是否为有向无环图
- 首先设立一个是队列q终于存储入度为0的结点,同时设置变量num初始化为0,用于记录加入队列中结点的数量;
- 然后弹出队首结点, 将队首结点能够到达的所有结点的入度都减一,如果这时有结点的入度变为0,那么则将该结点加入队列;
- 记得将弹出的结点能够到达的边清除,然后num++
- 最后判断,如果num == n即图结点的个数,那么为有向无环图
- 如果是要判断一个图是否为有向无环图,那么可使用以下代码:
vector G[MAXV];
int n, m, in[MAXV];
bool topologicalSort(){
int num = 0//用于记录进入结点的次数是否为结点的个数
queue q;
for(int i = 0; i < n; i++){
if(in[i] == 0){
q.push(i);
}
}
while(!q.empty()){
int u = q.front();
q.pop();
for(int i = 0; i < G[u].size(); i++){
int v = G[u][i];
in[v]--;
if(in[v] == 0){
q.push(v);
}
}
G[u].clear();
num++;
}
if(num == n) return true;
else return false;
}
二、参考代码
#include
#include
using namespace std;
//bool topologicalSort(vector G[], int inDegree[]){
// return;
//}
int main(){
int m, n, a, b, c, flag = 0;
scanf("%d%d", &n, &m);
//vector > v(n);//用于存储图
vector v[1010];
int inDegree[1010];//记录结点的入度
for(int i = 0; i < m; i++){
scanf("%d%d", &a, &b);
v[a].push_back(b);
inDegree[b]++;
}
int k;
scanf("%d", &k);
for(int i = 0; i < k; i++){
int judge = 1;
vector tin(inDegree, inDegree+n+1);
for(int j = 0; j < n; j++){
scanf("%d", &c);
if(tin[c] != 0) judge = 0;
//for(int l = 0; l < v[c].size(); l++) tin[v[c][l]]--;
for (int it : v[c]) tin[it]--;
}
if(judge == 1) continue;
printf("%s%d", flag == 1 ? " " : "", i);
flag = 1;
}
return 0;
}