拓扑排序

      对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。

   拓扑排序可以通过DFS来实现。在排序某一个节点时,首先等到它的所有儿子节点排序完成后,再排序它本身。拓扑排序基于这样一个事实:若u到v存在通路,则u一定排在v的前面。如果图有环,则将不可能排出拓扑序列。

/*UVa10305 - Ordering Tasks
---DFS进行拓扑排序
--*/
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 100 + 5;

vector<int>vec[maxn];  //邻接表
int vis[maxn];
int topo[maxn];
int t;

//默认顶点从0...n-1编号
bool dfs(int u){
	vis[u] = -1;  //等待排序
	for (int i = 0; i < (int)vec[u].size(); i++){
		int v = vec[u][i];
		if (vis[v] < 0)return false;  //存在环,排序失败
		else if (!vis[v] && !dfs(v))return false; //它的子节点排序失败
	}
	vis[u] =1; //标志当前节点排序完成
	topo[--t] = u;  //加入排序列表中
	return true;
}
bool toposort(int n){
	t = n;
	memset(vis, 0, sizeof(vis)); //初始态为未排序
	for (int i = 0; i < n; i++)if (!vis[i])
	      if (!dfs(i))return false;
	return true;
}
int main(){
	int m, n,u,v;
	while (scanf("%d%d",&n, &m)&&n){
		for (int i = 0; i < n; i++)vec[i].clear();
		
		for (int i = 0; i < m; i++){
			scanf("%d%d", &u, &v);
			u--; v--;
			vec[u].push_back(v);
		}
		toposort(n);
		printf("%d", topo[0]+1);
		for (int i = 1; i < n; i++)
			printf(" %d", topo[i]+1);
		printf("\n");
	}
	return 0;
}

  

posted @ 2016-09-01 13:34  曹孟德  阅读(201)  评论(0编辑  收藏  举报