Uva 10305 - Ordering Tasks(拓扑排序)

题目连接 https://vjudge.net/problem/UVA-10305c++


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.this

 

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

 

Sample Input.net

code

4 1 排序

2 2 input

3 1 it

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;
}
相关文章
相关标签/搜索