- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
topSort :: V.Vector ([Int], [Int])
-> Either String [Int]
topSort kob =
let
sup u k = do
let max i = (i,) . head . snd <$> k `MV.read` i
l <- mapM max u
case filter (uncurry (==)) l of
[(a,_)] -> return $ Right a
x -> return $ Left "Topology error"
rewrite k s (i, j) = do
let f x | x == s && j < 0 = []
| x == s = [j]
| otherwise = [x]
when (j>=0) $ MV.modify k (_1 %~ (i:)) j
MV.modify k (_2 %~ (>>= f)) i
go u k =
readSTRef u >>= \case
[a] -> return $ Right [a]
u_ -> sup u_ k >>= \case
Right s -> do
modifySTRef' u $ Data.List.delete s
s_d <- fst <$> MV.read k s
mapM_ (rewrite k s) $ zip s_d (tail s_d ++ [-1])
tail <- go u k
return $ (s:) <$> tail
Left err ->
return $ Left err
in runST $ do
u <- newSTRef $ [0..V.length kob-1]
k <- V.thaw kob
liftM reverse <$> go u k
CHayT 04.04.2017 09:40 # 0
roman-kashitsyn 04.04.2017 12:22 # 0
Я так понимаю, u — это список(sic!) ещё не посещённых вершин. Не понятно только, зачем нужен медленный список внутри мутабельной переменной, когда гораздо проще использовать мутабельный массив, как это делается в Data.Graph?
> Either String
тоже забавно, stringly typed programming
Ну и import Data.Graph (topSort), разумеется.
CHayT 04.04.2017 12:47 # 0
Сам высрал как прототип. Во время бессонницы, скажу в оправдание.
> Не понятно только, зачем нужен медленный список внутри мутабельной переменной, когда гораздо проще использовать мутабельный массив, как это делается в Data.Graph?
В основном потому что этот код мутировал из иммутабельного.
> import Data.Graph (topSort)
Это не просто граф, т.к. входные данные несут не только инвормацию о рёбрах, но ещё и об относительном порядке в результирующем массиве. Обычный топсорт её проебёт.
roman-kashitsyn 04.04.2017 13:03 # 0
Используй алгоритм Kahn-а вместо dfs, он может выдавать лексикографически-минимальную топологическую сортировку.
roman-kashitsyn 04.04.2017 13:30 # 0
Как видишь, для эффективности нужно иметь ещё и инвертированный граф, чтобы быстро находить рёбра, входящие в вершину ("incoming_edges(G, v)").
CHayT 04.04.2017 19:17 # 0
roman-kashitsyn 04.04.2017 21:16 # 0