Uva 10305 - Ordering Tasks(拓扑排序)

题目链接 https://vjudge.net/problem/UVA-10305


John has n tasks to do. Unfortunately, thetasks are not independent and the execution of one task is only possible ifother tasks have already been executed.

 

Input

The input will consist of several instancesof the problem. Each instance begins with a line containing two integers, 1 ≤ n≤ 100 and m. n is the number of tasks (numbered from 1 to n) and m is thenumber of direct precedence relations between tasks. After this, there will bem lines with two integers i and j, representing the fact that task i must beexecuted before task j. An instance with n = m = 0 will finish the input.

 

Output For each instance, print a line withn integers representing the tasks in a possible order of execution.

 

Sample Input

4 1 

2 2 

3 1 

3 1 

5 0 

0

Sample Output

3

 

 【题意】

 紫书167页例题。假设有n个变量,还有m个二元组(u,v),分别表示变量u<v,那么所有变量从小到大排列起来应该是什么样的呢假设有n个变量,还有m个二元组(u,v),分别表示变量u<v,那么所有变量从小到大排列起来应该是什么样的呢?例如有四个变量a,b,c,d,若已知a<b,c<b,d<c,则这四个变量的排序可能是a<d<c<b,尽管还有其他可能,但你只需找出其中的一个即可。


 

【思路】

 裸的拓扑排序问题,可以用数据结构书上讲的那种方法:选择一个0入度的顶点,删除它的所有有向边,再在剩余的结点中选择另一个0入度顶点,重复这个过程,选择顶点的顺序就是拓扑排序所得的序列。这里有一个更为简便的方法,仅仅需要dfs即可实现,和普通的dfs有所不同的是访问数组有三个值。used[v]==0表示顶点v没有被访问过,used[v]==1表示v的所有子孙和它本身都已经被访问过,used[v]==-1表示v的子孙正在被访问,即以v为根结点的dfs正在执行。

这样一来,即可判断有向图中是否有环,还能在没有环时求出拓扑序列。

坑点:判断m和n同时为0的条件容易想错。是(m||n)而不是(m&&n),画个真值表就明白了。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 150;

int m, n;
int from, to;
vector<int> G[maxn];
vector<int> ans;
int used[maxn];

void init() {
	ans.clear();
	memset(used, 0, sizeof(used));
	for (int i = 0; i < maxn; i++) G[i].clear();
}

bool dfs(int v) {
	used[v] = -1;
	for (int i = 0; i < G[v].size(); i++) {
		int u = G[v][i];
		if (-1 == used[u]) return false;
		if (0 == used[u] && !dfs(u)) return false;
	}
	used[v] = 1;
	ans.push_back(v);
	return true;
}

bool toposort() {
	for (int i = 1; i <= n; i++) {
		if (!used[i]) 
			if (!dfs(i)) return false;
	}
	return true;
}

int main() {
	while (scanf("%d%d", &n, &m) == 2 && (n || m)) {
		init();
		for (int i = 0; i < m; i++) {
			scanf("%d%d", &from, &to);
			G[from].push_back(to);
		}
		
		if (!toposort()) continue;
		
		reverse(ans.begin(), ans.end());
		for (int i = 0; i < ans.size(); i++) {
			printf("%d%c", ans[i], i + 1 == ans.size() ? '\n' : ' ');
		}
	}
	return 0;
}


posted @ 2017-12-19 16:11  不想吃WA的咸鱼  阅读(127)  评论(0编辑  收藏  举报