对一个有向无环图(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(" "); } return 0; }