大意:
对于DAG(有向无环图),把图中所有结点排序,使得每一条有向边(u, v)对应的u都排在v的前面。直观地说,就是用一条线把有向图
中所有点连起来(当然是遵循有向边的)。
注:①有环图是不存在拓扑排序的。(因此可以用来判断图是否有环)。
②一个DAG可能有多个拓扑序列。
实现:
主要有两种实现方法:
① bfs版:
(1)从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它.
(2)从网中删去该顶点,并且删去从该顶点发出的全部有向边.
(3)重复上述两步,直到剩余的网中不再存在没有前驱的顶点为止.
② dfs版:
详见代码。(by Rujia Liu)
带有环判断。
//从编号小的开始,【一直走,直到这条链走完,】 //再走另外的,于是不会破坏设定的二元关系 //================================================================ #include<stdio.h> #include<string.h> const int MAXN = 1000; int n, m, G[MAXN][MAXN]; int c[MAXN]; int topo[MAXN], t; bool dfs(int u){ c[u] = -1; for(int v = 0; v < n; v++) if(G[u][v]) { if(c[v]<0) return false; //正在访问,说明成环了 else if(!c[v]) dfs(v); //未访问 则访问它 } c[u] = 1; topo[--t]=u; //!!!加到当前拓扑序的首部 return true; } bool toposort(){ t = n; //t是n的temp memset(c, 0, sizeof(c)); //访问状态,初始为未访问过 0 -1 1 for(int u = 0; u < n; u++) if(!c[u]) if(!dfs(u)) return false; return true; } int main() { scanf("%d%d", &n, &m); //n个变量(默认0~n-1) m个二元组 memset(G, 0, sizeof(G)); for(int i = 0; i < m; i++) { int u, v; scanf("%d%d", &u, &v); G[u][v] = 1; //存在这个二元关系 u->v } if(toposort()) { for(int i = 0; i < n; i++) printf("%d/n", topo[i]); //正着输出的 } else //若存在有向环 printf("No/n"); }