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;
}
相關文章
相關標籤/搜索