Book--Topological Sort
什么拓扑排序呢?简单的说,有那么些个二元组(u,v),表示u要在v之前(u<v),现在要将所有元素按照二元组的规则排序。
好了,不扯了,看看度娘怎么讲的吧:对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若 ∈E(G),则u在线性序列中出现在v之前。
先来看看佳哥牛牛怎么想的:
int used[MAXN];//用来记录有没有访问过 int topo[MAXN] , t; bool dfs( int u ) { used[u] = -1;//表示已访问,且为当前访问点 for( int v = 0 ; v < n ; v ++ ) { if ( G[u][v] )//G的图应该事先建立成:有二元组关系的为1,其余的为0 { if ( used[v] < 0 ) return false;//存在有向环,返回false else if( !used[v] && !dfs( v )) return false;//事先未访问,且从该点深搜失败,返回false } } used[u] = 1; topo [ --t ] = u;//这个记录的顺序和二元组大小判断顺序相反(待验证) return true; } bool toposort( { t = n; memset( used , 0 , sizeof(used)); for( int u = 0 ; u < v ; u ++) { if ( !dfs(u) ) return false; } return true; }
没错,dfs思想在这里的确很神奇,看来真正难的是算法的思想,而非其代码。
下面,看看百科大大提供的:
实现的基本方法
拓扑排序方法如下:
(2)从网中删去该顶点,并且删去从该顶点发出的全部有向边.
(3)重复上述两步,直到剩余的网中不再存在没有前趋的顶点为止.
bool TopologicalSort(int a[][101]) //可以完成拓扑排序则返回True { int n = a[0][0], i, j; int into[101], ans[101]; memset(into, 0, sizeof(into)); memset(ans, 0, sizeof(ans)); for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { if (a[i][j] > 0) into[j]++;//into记录到某个点有多少条路(即作为二元组第二元素的次数) } } into[0] = 1;//为了配合下面的j=0;into[j]!=0 for (i = 1; i <= n; i++) { j = 0; while (into[j] != 0) { j++; if (j > n) return false; } ans[i] = j;//从前到后找到第一个是0使into【j】== 0 的 j 值 into[j] = -1;//相当于从图中删除该点 for (int k = 1; k <= n; k++) { if (a[j][k] > 0) into[k]--;//删从该点出发的所有有向边。 } } for (i = 1; i <= n; i++) { cout << ans[i] << " "; } cout << endl; return true; }