题目描述
在大学里面,很多课程的内容是有联系的,你只有先学习了某一门课程,才能够更好地理解另一门课程。比如,想要学好算法,你首先得学习高级语言程序设计、数据结构等课程。我们将这些课程称为它的前置课程。
现在假设你是某大学某个系的教务主任,该系的学生需要修满n门课程才能达到毕业要求,已知课程之间的前置关系,请你为该系的学生排课。
输入
第一个数为课程数n,课程之间的前置关系数m,课程的编号为0~n-1
接下来m行,每行2个整数u、v,表示u号课程是v号课程的前置课程。
输出
n个整数,用空格隔开,表示排课顺序。
输入样例
3 3
1 0
2 0
1 2
输出样例
1 2 0
仔细分析,发现该题应使用拓扑排序。
拓扑排序的定义及原理见 拓扑排序(侵删)
附注释的代码如下
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1001000;
int head[maxn], tot = 0, indeg[maxn];
int n, m, seq[maxn];
struct note{
int v, next;
} edge[maxn];
void add(int u,int v) {//图中加入 u -> v的结点
edge[tot].v=v;
edge[tot].next = head[u];
head[u]=tot++;
}
void topo(){
queue<int> q;
for(int i = 0; i < n; i++){
if(indeg[i] == 0) //入度为0直接入栈
q.push(i);
}
int seqs=0;
while(!q.empty()){
int u = q.front();
q.pop();
seq[seqs++] = u; //将该结点加入seq数组,即排在前面
for(int i = head[u]; i != -1 ; i = edge[i].next){
int v = edge[i].v;
indeg[v]--; // 删去包含u的边,u结点所连接的结点入度-1
if(indeg[v] == 0)
q.push(v);
}
}
for(int i=0;i<seqs;i++){
printf("%d ",seq[i]);
}
}
int main()
{
int x, y;
scanf("%d%d", &n, &m);
memset(head, -1, sizeof(head));
for(int i = 1; i <= m; i++){
scanf("%d%d", &x, &y);
add(x,y);
indeg[y]++; // y的入度+1
}
topo();
return 0;
}