标签:
链接:http://acm.hust.edu.cn/vjudge/problem/19494
分析:
题目中n个变量看成图中n个结点,图中的边即是二元关系,m个二元组就代表了这m条边表示的二元关系,(u,v)表示v大于u,从u向v连一条有向边,如果这m个二元组不矛盾,那么这个图便是一个DAG否则就存在一个有向环,解便不存在了,举个栗子a<b,b<c,可以推出a<c,但是现在出现了c连到了a意思是a>c,与之前的递推相悖,所以如果图中存在有向环,则不存在拓扑序,反之一个DAG图就存在拓扑序,拓扑序可以用DFS求。从图中的某个结点开始,用一个c数组标记,-1表示这个结点正在访问,那么如果再次访问到一个在c中被标记为-1的结点就说明存在一个有向环,0表示这个结点还未被访问,它的子孙有没有被访问不知道,因为有可能从它的子孙开始DFS,1表示这个结点以及它的子孙已经被访问过,每次DFS在访问完一个结点后把它加到当前拓扑序首部,因为只能保证向后已经访问完,我们不知道开始DFS的结点是否有父结点,所以如果前面还有结点肯定都比现在访问到的这些结点要小必须放在它们前面。
注意:m可以等于0!!
1 #include <cstdio> 2 #include <cstring> 3 4 const int maxn = 100 + 5; 5 6 int n, m, t, G[maxn][maxn], c[maxn], topo[maxn]; 7 8 bool dfs(int u) { 9 c[u] = -1; 10 for (int v = 1; v <= n; v++) if (G[u][v]) { 11 if (c[v] < 0) return false; 12 else if (!c[v] && !dfs(v)) return false; 13 } 14 c[u] = 1; topo[--t] = u; 15 return true; 16 } 17 18 bool toposort() { 19 t = n; 20 memset(c, 0, sizeof(c)); 21 for (int u = 1; u <= n; u++) if (!c[u]) 22 if (!dfs(u)) return false; 23 return true; 24 } 25 26 int main() { 27 while (scanf("%d%d", &n, &m) == 2 && n) { 28 memset(G, 0, sizeof(G)); 29 for (int i = 0; i < m; i++) { 30 int u, v; scanf("%d%d", &u, &v); 31 G[u][v] = 1; 32 } 33 toposort(); 34 printf("%d", topo[0]); 35 for (int i = 1; i < n; i++) printf(" %d", topo[i]); 36 printf("\n"); 37 } 38 return 0; 39 }
UVa10305 Ordering Tasks (拓扑排序)
标签:
原文地址:http://www.cnblogs.com/XieWeida/p/5831131.html