题目大意
有编号 1~n 为任务,给你 m 组数据,表示任务 i 需要在任务 j 之前完成,最后让你输出满足以上情况的结果(可能有多种结果,只要满足即可)。
解题思路
1、我们用 x (xian) 和 h (hou) 来代替题目中的 i 和 j ,以便理解且不容易出错。
2、开一个二维 bool 数组map [] []
输入数据时,每输入一个数据,若 map [x] [h] 为 false,则令 map [x] [h] 为 true,标记这组数据已被输入,防止重复计数。
3、开一个数组 indegree [],记录任务 h 前面有多少任务数。
每输入一个数据,就令 indegree[h] ++
4、开一个数组 ans [] 作为排序结果。
在函数 topo 中,对 indegree [] 进行遍历
如果找到 indegree [t] 为 0,代表这个任务前面没有任务,则将这个任务加到结果数组 ans[] 中,然后令 indegree [t] = -1,标记它已处理。
然后遍历 map [t] [j],若 map [t] [j] 不为 0,证明这个已处理的任务后面跟有任务,则令后面这个跟着的任务的 indegree [j] –
5、最后输出数组 ans [] 即可
扫描二维码关注公众号,回复:
13799308 查看本文章
复杂度分析
O(n)
算法资料
拓扑排序
心得体会
学会了基础的拓扑排序
代码
#include <stdio.h>
#include <string.h>
const int maxn = 105;
int n, m, x, h; //定义全局变量
bool map[maxn][maxn]; //判断这组数据是否被输入过,防止重复计数
int ans[maxn]; //拓扑排序结果
int indegree[maxn]; //排在 h前面的有多少
void topo() {
//进行拓扑排序
int k = 0;
int t;
for(int i=1; i<=n; i++) {
//多次遍历
for(int j=1; j<=n; j++) {
//遍历
if(indegree[j]==0) {
//若 j前面为空
t = j;
break;
}
}
ans[k++] = t; //依次加入排序结果中
indegree[t] = -1; //将其标记为已进行拓扑排序
for(int j=1; j<=n; j++) //遍历一次
if(map[t][j] != 0) //如果找到 t在 j前面的
indegree[j]--; //就令 j前面的数量减一,因为 t已经排序完成
}
//输出
for(int i=0; i<n-1; i++) //注意最后一个后面不加空格
printf("%d ", ans[i]);
printf("%d\n", ans[n-1]);
}
int main(void) {
while(scanf("%d %d", &n, &m) != EOF) {
if(n==0 && m==0) //结束条件
break;
//初始化
memset(map, 0, sizeof(map));
memset(indegree, 0, sizeof(indegree));
for(int i=0; i<m; i++) {
scanf("%d %d", &x, &h); //读入先后
if(map[x][h]==0) {
//若这组数据没有被输入过
indegree[h]++; //让 h前面的数量加 1
map[x][h] = 1; //标记这组数据已被输入
}
}
topo(); //进行拓扑排序并输出结果
}
return 0;
}