/// <summary>
        /// <para><paramref name="from"/> からの最短経路長をベルマン・フォード法で求める。負の長さにも使える</para>
        /// <para>計算量: O(|V|・|E|)</para>
        /// </summary>
        public static T[] BellmanFord <T, TOp, TNode, TEdge>(this IWGraph <T, TOp, TNode, TEdge> graph, int from)
            where T : struct
            where TOp : struct, INumOperator <T>
            where TNode : IGraphNode <TEdge>
            where TEdge : IWGraphEdge <T>
        {
            TOp op       = default;
            var graphArr = graph.AsArray();
            var INF      = op.Divide(op.MaxValue, op.Increment(op.MultiplyIdentity));
            var res      = new T[graphArr.Length];

            Array.Fill(res, INF);
            res[from] = default;

            for (int i = 1; i <= graphArr.Length; i++)
            {
                foreach (var node in graphArr)
                {
                    foreach (var e in node.Children)
                    {
                        var to = e.To;
                        var x  = op.Add(res[node.Index], e.Value);
                        if (op.GreaterThan(res[to], x))
                        {
                            res[to] = x;
                            if (i == graphArr.Length)
                            {
                                throw new InvalidOperationException("負の閉路");
                            }
                        }
                    }
                }
            }
            return(res);
        }
Beispiel #2
0
        /// <summary>
        /// <para><paramref name="from"/> からの最短経路長を01-BSFで求める。</para>
        /// <para>計算量: O(|E| + |V|)</para>
        /// </summary>
        public static T[] ShortestPath01BFS <T, TOp, TNode, TEdge>(this IWGraph <T, TOp, TNode, TEdge> graph, int from)
            where T : struct
            where TOp : struct, INumOperator <T>
            where TNode : IGraphNode <TEdge>
            where TEdge : IWGraphEdge <T>
        {
            TOp op       = default;
            var graphArr = graph.AsArray();
            var INF      = op.MaxValue;
            var res      = new T[graphArr.Length];

            System.Array.Fill(res, INF);
            res[from] = default;

            var used    = new bool[graphArr.Length];
            int count   = 0;
            var remains = new Deque <int>(graphArr.Length)
            {
                from
            };

            while (remains.Count > 0)
            {
                var ix = remains.PopFirst();
                if (used[ix])
                {
                    continue;
                }
                used[ix] = true;
                if (++count >= graphArr.Length)
                {
                    break;
                }
                var len = res[ix];
                foreach (var e in graphArr[ix].Children)
                {
                    var to         = e.To;
                    var nextLength = len;
                    if (EqualityComparer <T> .Default.Equals(e.Value, default))
                    {
                        if (op.GreaterThan(res[to], nextLength))
                        {
                            res[to] = nextLength;
                            remains.AddFirst(to);
                        }
                    }
                    else
                    {
                        nextLength = op.Increment(nextLength);
                        if (op.GreaterThan(res[to], nextLength))
                        {
                            res[to] = nextLength;
                            remains.AddLast(to);
                        }
                    }
                }
            }
            return(res);
        }
        /// <summary>
        /// <para><paramref name="from"/> からの最短経路長をダイクストラ法で求める。</para>
        /// <para>計算量: O( (|E| + |V|) log |V| )</para>
        /// </summary>
        public static T[] Dijkstra <T, TOp, TNode, TEdge>(this IWGraph <T, TOp, TNode, TEdge> graph, int from)
            where T : struct
            where TOp : struct, INumOperator <T>
            where TNode : IGraphNode <TEdge>
            where TEdge : IWGraphEdge <T>
        {
            TOp op       = default;
            var graphArr = graph.AsArray();
            var INF      = op.MaxValue;
            var res      = new T[graphArr.Length];

            System.Array.Fill(res, INF);
            res[from] = default;

            var used    = new bool[graphArr.Length];
            int count   = 0;
            var remains = new PriorityQueueDijkstra <T, TOp>(graphArr.Length);

            remains.Enqueue(default, from);
Beispiel #4
0
        /// <summary>
        /// <para>各頂点間の最短経路長をワーシャルフロイド法で求める</para>
        /// <para>計算量: O(|V|^3)</para>
        /// </summary>
        public static T[][] WarshallFloyd <T, TOp, TNode, TEdge>(this IWGraph <T, TOp, TNode, TEdge> graph)
            where T : struct
            where TOp : struct, INumOperator <T>
            where TNode : IGraphNode <TEdge>
            where TEdge : IWGraphEdge <T>
        {
            TOp op       = default;
            var graphArr = graph.AsArray();
            var INF      = op.Divide(op.MaxValue, op.Increment(op.MultiplyIdentity));
            var res      = new T[graphArr.Length][];

            for (var i = 0; i < graphArr.Length; i++)
            {
                res[i] = new T[graphArr.Length];
                System.Array.Fill(res[i], INF);
                res[i][i] = default;
                foreach (var e in graphArr[i].Children)
                {
                    res[i][e.To] = e.Value;
                }
            }
            for (var k = 0; k < graphArr.Length; k++)
            {
                for (var i = 0; i < graphArr.Length; i++)
                {
                    for (var j = 0; j < graphArr.Length; j++)
                    {
                        var x = op.Add(res[i][k], res[k][j]);
                        if (op.GreaterThan(res[i][j], x))
                        {
                            res[i][j] = x;
                        }
                    }
                }
            }
            return(res);
        }