目录

​1,题目描述​

​ 题目大意​

​知识补充——拓扑排序​

​问题的引入——AOV网​

​拓扑排序​

​算法实现​

​2,思路​

​3,AC代码​

​4,解题过程​


1,题目描述

PAT_甲级_1146 Topological Order (25point(s)) (C++)【拓扑排序】_拓扑排序

PAT_甲级_1146 Topological Order (25point(s)) (C++)【拓扑排序】_PAT_02

Sample Input:

6 8
1 2
1 3
5 2
5 4
2 3
2 6
3 4
6 4
5
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:

3 4

 题目大意

给出一个有向图,判断给出的序列是否为拓扑序列。

 

知识补充——拓扑排序

(以下内容来自百度百科,晴神笔记) 

问题的引入——AOV网

一个较大的工程往往被划分成许多子工程,我们把这些子工程称作活动(activity)。在整个​​工程​​中,有些子工程(活动)必须在其它有关子工程完成之后才能开始,也就是说,一个子工程的开始是以它的所有前序子工程的结束为先决条件的,但有些子工程没有先决条件,可以安排在任何时间开始。为了形象地反映出整个工程中各个子工程(活动)之间的先后关系,可用一个有向图来表示,图中的顶点代表活动(子工程),图中的有向边代表活动的先后关系,即有向边的起点的活动是终点活动的前序活动,只有当起点活动完成之后,其终点活动才能进行。通常,我们把这种顶点表示活动、边表示活动间先后关系的有向图称做顶点活动网(Activity On Vertex network),简称AOV网。

拓扑排序

拓扑排序是将有向无环图G的所有顶点排成一个线性序列,使得对图G中的任意两个顶点u、v,如果存在边u->v,那么在序列中u- -定在v前面。这个序列又被称为拓扑序列。

算法实现

  1. 定义一个队列Q,并把所有入度为0的结点加入队列。
  2. 取队首结点,输出。然后删去所有从它出发的边,并令这些边到达的顶点的入度减1,如果某个顶点的入度减为0,则将其加入队列。
  3. 反复进行2操作,直到队列为空。如果队列为空时入过队的结点数目恰好为N,说明拓扑排序成功,图G为有向无环图;否则,拓扑排序失败,图G中有环。

可使用邻接表实现拓扑排序。显然,由于需要记录结点的入度,因此需要额外建立一一个数组inDegree[MAXV],并在程序一开始读 入图时就记录好每个结点的入度。

 

2,思路

题目比较简单,只是判断序列是否为拓扑序列即可。

1,构建图,并统计每个节点的入度;

PAT_甲级_1146 Topological Order (25point(s)) (C++)【拓扑排序】_PAT_03

2,针对给定的序列,依次判断一个点,若当前点入度为0,则将其所有的邻接点入读减一,继续判断下一个;否则,即可判定不是拓扑序列;

PAT_甲级_1146 Topological Order (25point(s)) (C++)【拓扑排序】_甲级_04

 

3,AC代码

#include<bits/stdc++.h>
using namespace std;
int N, M, K, inDegree[1005], inTemp[1005]; //Nd顶点数 M有向边数 K查询数目
vector<int> ans, graph[1005];
bool judge(int temp[]){ // 判断是否为拓扑序列 true是 false不是
memcpy(inTemp, inDegree, (N+1) * sizeof(int)); // !!!节点编号从1开始 所以是N+1
for(int i = 0; i < N; i++){
if(inTemp[temp[i]] == 0){
for(auto it : graph[temp[i]])
inTemp[it]--; // 该节点temp[i]对应的所有相邻节点入度减一
}else return false;
}
return true;
}
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
scanf("%d%d", &N, &M);
int a, b;
for(int i = 0; i < M; i++){
scanf("%d%d", &a, &b);
graph[a].push_back(b);
inDegree[b]++; // 有向边指向的顶点入度加一
}
scanf("%d", &K);
int temp[N];
for(int i = 0; i < K; i++){
for(int j = 0; j < N; j++) // 获取拓扑序列
scanf("%d", &temp[j]);
if(!judge(temp))
ans.push_back(i);
}
for(int i = 0; i < ans.size(); i++)
printf("%d%c", ans[i], i == ans.size()-1 ? '\n':' ');
return 0;
}

4,解题过程

一发入魂o(* ̄▽ ̄*)ブ

PAT_甲级_1146 Topological Order (25point(s)) (C++)【拓扑排序】_PAT_05