观察问题
要找出合理的排列顺序,首先得决定第一点!知道如何找出第一点,那么就可以循序渐进的再找出第二点、第三点了。
可以作为第一点的点,想必它不必排在其他点后方。也就是说,没有被任何边连向的点,就可以作为第一点。如果有很多个第一点,那么找哪一点都行。
![](http://www.csie.ntnu.edu.tw/~u91029/TopologicalSort5.png)
决定第一点之后,那么剩下所有点都会在第一点后方。也就是说,由第一点连出去的边,其先后规定已经被满足了,规定存不存在都无所谓。因此,决定第一点之后,就可以删去此点,以及删去由此点连出去的边──原问题可以递回地缩小!
![](http://www.csie.ntnu.edu.tw/~u91029/TopologicalSort6.png)
只要反覆的寻找没有被任何边连向的点,然后删去此点以及删去由此点连出去的边,就可以找出一个合理的排列顺序了。
附带一提,要找出合理的排列顺序,也可以由最后一点开始决定!无论要从第一点找到最后一点,或是从最后一点找到第一点,都是可以的。各位可以想想看该怎么做。
找出一个合理的排列顺序( adjacency matrix )
尽管这个问题有Recursive 的性质,可以用递回实作,但由于递回的分支只有一条,故亦可以用回圈实做。我想大家都会选择以比较简单的回圈方式来实做吧?
实作时可以利用变数纪录图上每一个点目前仍被多少条边连到。寻找没有被任何边连向的点,就直接看该变数是不是零;删去由此点连出去的边,就顺便更新变数的值。
![](http://www.csie.ntnu.edu.tw/~u91029/TopologicalSort7.png)
- bool adj [ 9 ][ 9 ];
- int ref [ 9 ];
-
- void topological_sort ()
- {
- for ( int i = 0 ; i < 9 ; ++ i ) ref [ i ] = 0 ;
-
-
- for ( int i = 0 ; i < 9 ; ++ i )
- for ( int j = 0 ; j < 9 ; ++ j )
- if ( adj [ i ][ j ])
- ref [ j ]++;
-
-
- for ( int i = 0 ; i < 9 ; ++ i )
- {
-
- int s = 0 ;
- while ( s < 9 && ref [ s ] != 0 ) ++ s;
-
- if ( s == 9 ) break ;
- ref [ s ] = - 1 ;
-
- cout << s ;
-
-
- for ( int t = 0 ; t < 9 ; ++ t )
- if ( adj [ s ][ t ])
- ref [ t ]--;
- }
- }
找出一个合理的排列顺序( adjacency lists )
- int adj [ 9 ][ 9 ], size [ 9 ];
- int ref [ 9 ];
-
- void topological_sort ()
- {
- for ( int i = 0 ; i < 9 ; ++ i ) ref [ i ] = 0 ;
-
-
- for ( int i = 0 ; i < 9 ; ++ i )
- for ( int j = 0 ; j < size [ i ]; ++ j )
- ref [ adj [ i ][ j ]]++;
-
-
- queue < int > Q ;
- for ( int i = 0 ; i < 9 ; ++ i )
- if ( ref [ i ] == 0 )
- Q . push ( i );
-
-
- for ( int i = 0 ; i < 9 ; ++ i )
- {
-
- if ( Q . empty ()) break ;
- int s = Q . front (); Q . pop ();
- ref [ s ] = - 1 ;
-
- cout << s ;
-
-
- for ( int j = 0 ; j < size [ s ]; ++ j )
- {
- int t = adj [ s ][ j ];
- ref [ t ]--;
- if (! ref [ t ]) Q . push ( t );
- }
- }
- }
时间复杂度
时间复杂度等于一次Graph Traversal 的时间。图的资料结构为adjacency matrix 的话,便是O(V^2) ;图的资料结构为adjacency lists 的话,便是O(V+E) 。
UVa 10305 200
找出所有合理的排列顺序
请用backtracking 。此处不详述了,直接看练习题吧。
UVa 124
计算所有合理的排列顺序个数
需要使用Dynamic Programming 解决,时间复杂度O(2^V * V^2) 。
http://blog.csdn.net/tiaotiaoyly/article/details/2712349
小游戏:http://www.newgrounds.com/portal/view/527022。