10305 - Ordering Tasks(拓扑序列)

71 篇文章 0 订阅
14 篇文章 0 订阅

题目:10305 - Ordering Tasks


题目大意:给出几个任务的先后顺序,推出可能的排序。并不一定是唯一的。


解法一:

1,找出没有前驱,且没有访问过的点,放在拓扑序列的头部,,,2,删掉他所有想关连的边,并标记访问过。再次找出没有前驱的点,重复前面两个步骤,直到所有的点都访问过位置,输出拓扑序列。

#include<stdio.h>
#include<string.h>

const int N = 105;
int m, n, x, y, t;
int G[N][N], visit[N], topo[N];

int find() {
	
	int count  = 0;
	for(int i = 1; i <= n; i++) {

		for(int j = 1; j <= n; j++)  {

			if(G[j][i])
				count++;
		}
		if(count == 0 && !visit[i])
			return i;
		else
			count = 0;
	}
	return -1;

}

void delet(int k) {
	
	visit[k] = 1;
	topo[t++] = k;
	for(int i = 1; i <= n; i++)
		if(G[k][i]) {

			G[k][i] = 0;
		}

}

int main() {

	while(scanf("%d%d", &n, &m) , n || m) {
		
		int i;
		t = 0;
		memset(G, 0, sizeof(G));
		memset(visit, 0, sizeof(visit));
		for( i = 0; i < m; i++) {

			scanf("%d%d", &x, &y);
			G[x][y] = 1;
		}

		int s = find();
		while(s != -1) {

			delet(s);
			s = find();
		}

		for(i = 0; i < n; i++)
			if(i != n - 1)
			printf("%d ", topo[i]);
			else
				printf("%d\n", topo[i]);
	}
	return 0;
}


解法二:

            s[i]里面存放的是i完成后,才能开始的任务集合; 如果存在环,那么显然不存在拓扑排序。利用dfs来进行拓扑排序,每次将访问结束的结点放在当前拓扑序列的首部。


#include <cstdio>
#include <vector>
#include <cstring>

using namespace std;

const int maxn = 105;
vector<int> s[maxn];
int c[maxn], t;
int topu[maxn];

bool dfs (int k) {

	c[k] = -1;                                          //正在访问,判环用的
	int len = s[k].size();
	int tmp;
	for (int i = 0; i < len; i++) {
		tmp = s[k][i];
		if (c[tmp] == -1)                          //存在有向环
			return false;
		else if (!c[tmp] && !dfs(tmp))             //存在有向环
			return false;
	}
	c[k] = 1;                                           //不要忘记访问完之后要将这个结点置位1,表示已经访问过;
	topu[t--] = k;                                      //每次访问完改节点,如果没有出现环,那么就将这个结点放在当前拓扑序列的首部(为什么不放在尾部)那是因为可能下次会有一个结点u,存在这个u -> k 的关系,这个时候,如果放在尾部的话,之前的关系是k - > k1->k2->k3,突然出现了u,明显不能接在后面,所以放在首部  k3<-k2<-k1<-k,那么这时候的u放在首部符合要求;
        return true;
}

bool topuSort (int n) {

	t = n;
	memset (c, 0, sizeof(c));
	for (int i = 1; i <= n; i++)
		if (!c[i] && !dfs(i))
			return false;
	return true;
}

int main () {

	int n, m;
	int pre, next;
	while (scanf ("%d%d", &n, &m) && (n || m)) {

		for (int i = 0; i < maxn; i++)
			s[i].clear();
		for (int i = 0; i < m; i++) {
			scanf ("%d%d", &pre, &next);
			s[pre].push_back(next);
		}
		
		if (topuSort(n)) {
			for (int i = 1; i < n; i++) 
				printf ("%d ", topu[i]);
			printf ("%d\n", topu[n]);
		}
	}
	return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值