LeetCode 743. Network Delay Time in F#

URL

leetcode.com/problems/network-delay-time

Code

github.com/syohex/dotnet-study/blob/master/..

#r "nuget:FSharpx.Collections"

open System
open FSharpx.Collections

[<CustomEquality; CustomComparison>]
type Data =
    { Node: int
      Cost: int }

    override this.GetHashCode() = hash this

    override this.Equals other =
        match other with
        | :? Data as o -> this.Node = o.Node && this.Cost = o.Cost
        | _ -> failwith "cannot compare with other types"

    interface System.IComparable with
        member this.CompareTo other =
            match other with
            | :? Data as o -> compare this.Cost o.Cost
            | _ -> failwith "cannot compare with other types"

let timesToGraph (times: (int * int * int) list) : Map<int, (int * int) list> =
    times
    |> List.fold
        (fun acc (node, next, cost) ->
            match Map.tryFind node acc with
            | Some (v) -> Map.add node ((next, cost) :: v) acc
            | None -> Map.add node [ (next, cost) ] acc)
        Map.empty

let rec networkDelayTime'
    (q: IPriorityQueue<Data>)
    (graph: Map<int, (int * int) list>)
    (visited: Set<int>)
    (costs: int [])
    : unit =
    match PriorityQueue.tryPop q with
    | None -> ()
    | Some ((d, rest)) ->
        let visited' = Set.add d.Node visited
        costs.[d.Node-1] <- Math.Min(costs.[d.Node-1], d.Cost)

        match Map.tryFind d.Node graph with
        | None -> networkDelayTime' rest graph visited' costs
        | Some (nexts) ->
            let q' =
                nexts
                |> List.filter (fun (next, _) -> Set.contains next visited' |> not)
                |> List.fold
                    (fun acc (next, cost) -> PriorityQueue.insert { Node = next; Cost = d.Cost + cost } acc)
                    rest

            networkDelayTime' q' graph visited' costs


let networkDelayTime (times: (int * int * int) list) (n: int) (k: int) : int =
    let graph = timesToGraph times

    let q =
        PriorityQueue.empty false
        |> PriorityQueue.insert { Node = k; Cost = 0 }

    let costs = Array.init n (fun _ -> Int32.MaxValue)
    networkDelayTime' q graph Set.empty costs

    match Array.tryFind ((=) Int32.MaxValue) costs with
    | Some (_) -> -1
    | None -> Array.max costs