- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
import qualified Data.Map as M
import Data.Maybe
import Data.Array
import Control.Monad
import Control.Monad.State
import Control.Monad.IfElse
type Graph = Array Int [Int]
isBipartite g = isJust $ runStateT (mapM_ fill (indices g)) M.empty
where
fill v = whenM (M.notMember v`fmap`get) $ spread True v
spread k v = whenM (paint k v) $ mapM_ (spread (not k)) (g!v)
paint k v = get >>= \c -> case M.lookup v c of
Nothing -> put (M.insert v k c) >> return True
Just x|x==k -> return False
|True -> fail ""
Проверка двудольности графа.
http://antilamer.livejournal.com/298055.html?format=light
roman-kashitsyn 06.08.2015 10:59 # 0
imihajlov 06.08.2015 11:10 # 0
Просто кто-то слишком любит обмазываться говном использовать монады.
roman-kashitsyn 06.08.2015 11:15 # 0
Изящно превратив линейный алгоритм в квадратичный? Map тогда уж, так заплатим хотя бы логарифмом.
bormand 06.08.2015 11:05 # +2
Dummy00001 06.08.2015 11:37 # +2
kegdan 06.08.2015 12:29 # 0
Vasiliy 06.08.2015 13:27 # 0
Мне вот это монада нравится.
bormand 06.08.2015 14:13 # +1
kegdan 06.08.2015 14:37 # 0
kegdan 06.08.2015 16:29 # 0
Оцените говнистость
roman-kashitsyn 06.08.2015 16:35 # 0
kegdan 06.08.2015 16:50 # 0
Меня больше интересует говнистость - мне ж на работу когда нибудь придется устраиваться. На джуниора тянет?
bormand 06.08.2015 16:52 # 0
Ну офигеть как удобнее. Сканить всю строку вместо того, чтобы тупо пробежаться по списку нужных рёбер.
kegdan 06.08.2015 16:53 # 0
Хотя я давно этим не занимался, он скорее нагляднее, а удобность еще нужно обмозговать
bormand 06.08.2015 17:02 # +1
Да ну... На практике графы всё-таки разряжённые. И в итоге твоя матрица жрёт овердохуя памяти O(N^2) и ищет соседние узлы за O(N).
И всё это ради одной почти никому нинужной операции за O(1) - получить edge между двумя узлами. Причём adjacency list, если его реализовать через Set, может справиться с ней за O(log(M)), где M - количество исходящих из первой ноды рёбер, что вполне приемлемо.
kegdan 06.08.2015 17:05 # 0
В adjacency matrix проще редактировать и искать входящие в вершину ребра.
bormand 06.08.2015 17:07 # 0
Если это настолько нужно - можно и обратные списки сохранить. Память вырастет всего вдвое, а не пропорционально квадрату :)
Но можно пример, где это нужно?
> редактировать
Да ну. Вставки в set/list тоже примитивны.
roman-kashitsyn 06.08.2015 17:39 # 0
Обычно проще один раз построить граф, в котором все рёбра инвертированы.
А если граф не ориентированный, то вообще ничего делать не нужно.
kegdan 06.08.2015 17:40 # 0
kegdan 06.08.2015 17:48 # 0
https://ideone.com/Mf5rDd
roman-kashitsyn 06.08.2015 16:56 # +2
Матрица реально нужна, например, в Флойде-Уоршелле, но там сам алгоритм кубический.
bormand 06.08.2015 16:59 # 0
Это который с тройным циклом?
roman-kashitsyn 06.08.2015 17:00 # +1