UVA 10305 Ordering Tasks(拓扑排序)

题目大意

有编号 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;
}

猜你喜欢

转载自blog.csdn.net/weixin_51250927/article/details/114292011