コード例 #1
0
        private void InitializePreflow(AdjacencyListGraph <T> graph
                                       , AdjacencyVertex <T> source)
        {
            var vertexs = graph.GetVertexs();

            foreach (var vertex in vertexs)
            {
                vertex.Height  = 0;
                vertex.Preflow = 0;
            }

            var edges = graph.GetEdges();

            foreach (FlowEdge <T> edge in edges)
            {
                edge.Flow            = 0;
                edge.Revolution.Flow = 0;
            }

            source.Height = vertexs.Count();

            var sourceEdges = graph.GetVertexEdge(source);

            foreach (FlowEdge <T> sourceEdge in sourceEdges)
            {
                sourceEdge.Flow            = sourceEdge.Capacity;
                sourceEdge.Revolution.Flow = -sourceEdge.Capacity;
                sourceEdge.End.Preflow     = sourceEdge.Capacity;
                source.Preflow             = source.Preflow - sourceEdge.Capacity;
            }
        }
コード例 #2
0
        /// <summary>
        /// 单源最短路径会把一个点到其它所有点的最短路径算出来
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="graph"></param>
        /// <param name="source"></param>
        /// <param name="weightFuc"></param>
        /// <returns></returns>
        public static bool BellmanFord <T>(
            this AdjacencyListGraph <T> graph,
            AdjacencyVertex <T> source,
            Func <AdjacencyListGraph <T>, AdjacencyVertex <T>, AdjacencyVertex <T>, int> weightFuc
            ) where T : IEquatable <T>
        {
            graph.InitializeSingleSource(source);

            for (int i = 1; i <= graph.VertexLenght; i++)
            {
                foreach (var edge in graph.GetEdges())
                {
                    graph.Relax(edge.Start, edge.End, weightFuc);
                }
            }

            foreach (var edge in graph.GetEdges())
            {
                if (edge.Start.WeightBound >
                    Add(edge.End.WeightBound, weightFuc(graph, edge.Start, edge.End)))
                {
                    return(false);
                }
            }

            return(true);
        }
コード例 #3
0
        public static void Relax <T>(
            this AdjacencyListGraph <T> graph,
            AdjacencyVertex <T> first,
            AdjacencyVertex <T> second,
            Func <AdjacencyListGraph <T>, AdjacencyVertex <T>, AdjacencyVertex <T>, int> weightFuc
            ) where T : IEquatable <T>
        {
            var newBound = Add(first.WeightBound, weightFuc(graph, first, second));

            if (second.WeightBound > newBound)
            {
                second.WeightBound = newBound;
                second.Predecessor = first;
            }
        }
コード例 #4
0
        public static void InitializeSingleSource <T>(
            this AdjacencyListGraph <T> graph,
            AdjacencyVertex <T> source
            ) where T : IEquatable <T>
        {
            var vertexs = graph.GetVertexs();

            foreach (var vertex in vertexs)
            {
                vertex.WeightBound = int.MaxValue;
                vertex.Predecessor = null;
            }

            source.WeightBound = 0;
        }
コード例 #5
0
        /// <summary>
        /// 单源最短路径会把一个点到其它所有点的最短路径算出来
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="graph"></param>
        /// <param name="source"></param>
        /// <param name="weightFuc"></param>
        /// <returns></returns>
        public static void Dijkstra <T>(
            this AdjacencyListGraph <T> graph,
            AdjacencyVertex <T> source,
            Func <AdjacencyListGraph <T>, AdjacencyVertex <T>, AdjacencyVertex <T>, int> weightFuc
            ) where T : IEquatable <T>
        {
            graph.InitializeSingleSource(source);

            var calcVertexs = new List <AdjacencyVertex <T> >();

            var vertexs = graph.GetVertexs().ToList();

            //不想再增加AdjacencyVertex对象的负担了

            var queue = new ExtentionBinanyHeap <AdjacencyVertex <T> >
                        (
                vertexs,
                (first, second) =>
            {
                return(first.WeightBound < second.WeightBound);
            }
                        );

            //  while (!queue.IsEmpty) 竟然把while写成if有才
            while (!queue.IsEmpty)
            {
                var min = queue.Extract();

                Console.WriteLine("calcVertex");
                Console.WriteLine(min);

                calcVertexs.Add(min);

                var edges = graph.GetVertexEdge(min);
                foreach (var edge in edges)
                {
                    var oldWeight = edge.End.WeightBound;
                    Relax(graph, edge.Start, edge.End, weightFuc);

                    //没有索引位置一下让我傻逼了!网上找了一下也是有调整的。
                    if (oldWeight != edge.End.WeightBound)
                    {
                        queue.UpdateKey(edge.End, edge.End);
                    }
                }
            }
        }
コード例 #6
0
        /// <summary>
        /// MST
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="graph"></param>
        /// <param name="weightFunc"></param>
        /// <returns></returns>
        public static IEnumerable <AdjacencyEdge <T> > GetMininumSpanningTreeKruskal <T>(
            this AdjacencyListGraph <T> graph,
            Func <AdjacencyEdge <T>, int> weightFunc
            ) where T : IEquatable <T>
        {
            var vertexs = graph.GetVertexs();
            var edges   = graph.GetEdges().ToList();

            var sets = new Dictionary <AdjacencyVertex <T>, DisjointSet <AdjacencyVertex <T> > >();

            var result = new List <AdjacencyEdge <T> >();

            foreach (var vertex in vertexs)
            {
                sets[vertex] = (new DisjointSet <AdjacencyVertex <T> >(vertex));
            }

            foreach (var edge in edges)
            {
                edge.Weight = weightFunc(edge);
            }

            //吃自己写的狗粮,这狗粮不好吃啊
            var sort      = new QuickSort();
            var sortEdges = sort.Sort(edges, (f, s) => f.Weight.CompareTo(s.Weight) > 0);

            foreach (var sortEdge in sortEdges)
            {
                var startDisjointSet = sets[sortEdge.Start];
                var endDisjointSet   = sets[sortEdge.End];

                DisjointSet <AdjacencyVertex <T> > newSet;

                if (startDisjointSet.Find(startDisjointSet.GetNode(sortEdge.Start))
                    != endDisjointSet.Find(endDisjointSet.GetNode(sortEdge.End)))
                {
                    newSet = startDisjointSet.Union(endDisjointSet);

                    result.Add(sortEdge);
                    sets[sortEdge.Start] = newSet;
                    sets[sortEdge.End]   = newSet;
                }
            }

            return(result);
        }
コード例 #7
0
        public int GenericPushRelabel(
            AdjacencyListGraph <T> graph
            , AdjacencyVertex <T> source
            , AdjacencyVertex <T> target
            )
        {
            var maxFolw = 0;

            InitializePreflow(graph, source);


            while (true)
            {
            }

            return(maxFolw);
        }
コード例 #8
0
        /// <summary>
        /// 怎么输出最小生成树?
        /// 很神奇的是这个贪心算法是对的
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="graph"></param>
        /// <param name="root"></param>
        /// <param name="weightFunc"></param>
        public static IList <AdjacencyEdge <T> > GetMininumSpanningTreePrim <T>(
            this AdjacencyListGraph <T> graph,
            AdjacencyVertex <T> root,
            Func <AdjacencyEdge <T>, int> weightFunc
            ) where T : IEquatable <T>
        {
            var vertexs = graph.GetVertexs().ToList();

            //TempStorage顶点到到某一顶点相连的最小权值。
            foreach (var vertex in vertexs)
            {
                vertex.TempStorage = int.MaxValue;
                vertex.Predecessor = null;
            }
            root.TempStorage = 0;


            var result = new List <AdjacencyEdge <T> >();

            var queue = new ExtentionBinanyHeap <AdjacencyVertex <T> >(vertexs, (f, s) => f.TempStorage < s.TempStorage);

            while (!queue.IsEmpty)
            {
                var min = queue.Extract();
                if (min != root)
                {
                    result.Add(graph.GetEdge(min.Predecessor, min));
                }

                var edges = graph.GetVertexEdge(min);
                foreach (var edge in edges)
                {
                    var weight = weightFunc(edge);
                    //TODO: 还有一个包含判断
                    if (edge.End.BelongedHeap == queue && weight < edge.End.TempStorage)
                    {
                        edge.End.Predecessor = min;
                        edge.End.TempStorage = weight;
                        queue.UpdateKey(edge.End, edge.End);
                    }
                }
            }

            return(result);
        }
コード例 #9
0
        public IDictionary <AdjacencyVertex <T>, FlowEdge <T> > GetResidualPath(
            AdjacencyListGraph <T> graph
            , AdjacencyVertex <T> source
            , AdjacencyVertex <T> target)
        {
            var path = new Dictionary <AdjacencyVertex <T>, FlowEdge <T> >();

            var vertexs = graph.GetVertexs();

            foreach (var vertex in vertexs)
            {
                vertex.Predecessor = null;
            }

            path[source] = null;

            var queue = new Queue <AdjacencyVertex <T> >();

            queue.Enqueue(source);

            while (!queue.IsEmpty)
            {
                var current      = queue.Dequeue();
                var currentEdges = graph.GetVertexEdge(current);
                foreach (FlowEdge <T> currentEdge in currentEdges)
                {
                    if (currentEdge.End != source &&
                        currentEdge.End.Predecessor == null &&
                        currentEdge.Capacity > currentEdge.Flow
                        )
                    {
                        path[currentEdge.End]       = currentEdge;
                        currentEdge.End.Predecessor = current;
                        queue.Enqueue(currentEdge.End);
                    }
                }
            }

            if (target.Predecessor == null)
            {
                return(null);
            }

            return(path);
        }
コード例 #10
0
        /// <summary>
        /// 看不懂算法导论上的实现
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="source"></param>
        /// <param name="target"></param>
        public int EdmondsKarp(
            AdjacencyListGraph <T> graph
            , AdjacencyVertex <T> source
            , AdjacencyVertex <T> target)
        {
            var maxflow = 0;

            var edges = graph.GetEdges().Select(d => d as FlowEdge <T>);

            foreach (var edge in edges)
            {
                edge.Flow = 0;
            }


            while (true)
            {
                var path = GetResidualPath(graph, source, target);
                if (path == null || path.Count == 0)
                {
                    break;
                }
                var tempFlow = int.MaxValue;

                //感觉第一次写这样的for循环
                for (var edge = path[target]; edge != null; edge = path[edge.Start])
                {
                    tempFlow = Math.Min(tempFlow, edge.ResidualCapacity);
                }

                Console.WriteLine();
                Console.WriteLine($"pathflow:{tempFlow}");

                for (var edge = path[target]; edge != null; edge = path[edge.Start])
                {
                    edge.Flow            = edge.Flow + tempFlow;
                    edge.Revolution.Flow = edge.Revolution.Flow - tempFlow;
                    Console.WriteLine($"edge:{edge}");
                }

                maxflow = maxflow + tempFlow;
            }

            return(maxflow);
        }
コード例 #11
0
        /// <summary>
        /// 获取连通图的算法是我有信心感觉我自己想的结构是对的,之后继续再验证。
        /// </summary>
        /// <param name="graph"></param>
        /// <returns></returns>
        public static IEnumerable <DisjointSet <AdjacencyVertex <T> > > GetConnectedComponenets <T>
        (
            this AdjacencyListGraph <T> graph
        ) where T : IEquatable <T>
        {
            var vertexs = graph.GetVertexs();
            var edges   = graph.GetEdges();

            var sets = new Dictionary <AdjacencyVertex <T>, DisjointSet <AdjacencyVertex <T> > >();

            var result = new List <DisjointSet <AdjacencyVertex <T> > >();



            foreach (var vertex in vertexs)
            {
                sets[vertex] = (new DisjointSet <AdjacencyVertex <T> >(vertex));
            }

            foreach (var edge in edges)
            {
                var startDisjointSet = sets[edge.Start];
                var endDisjointSet   = sets[edge.End];

                DisjointSet <AdjacencyVertex <T> > newSet;

                if (startDisjointSet.Find(startDisjointSet.GetNode(edge.Start))
                    != endDisjointSet.Find(endDisjointSet.GetNode(edge.End)))
                {
                    newSet = startDisjointSet.Union(endDisjointSet);

                    sets[edge.Start] = newSet;
                    sets[edge.End]   = newSet;


                    if (!result.Contains(newSet))
                    {
                        result.Add(newSet);
                    }
                }
            }
            return(result);
        }
コード例 #12
0
        /// <summary>
        /// 有向无回路图
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="graph"></param>
        /// <param name="source"></param>
        /// <param name="weightFuc"></param>
        /// <returns></returns>
        public static void DAGShortestPath <T>(
            this AdjacencyListGraph <T> graph,
            AdjacencyVertex <T> source,
            Func <AdjacencyListGraph <T>, AdjacencyVertex <T>, AdjacencyVertex <T>, int> weightFuc
            ) where T : IEquatable <T>
        {
            graph.TopologicalSort();

            graph.InitializeSingleSource(source);

            var vertexs = graph.GetVertexs();

            foreach (var orderVertex in vertexs)
            {
                var edges = graph.GetVertexEdge(orderVertex);

                foreach (var edge in edges)
                {
                    graph.Relax(edge.Start, edge.End, weightFuc);
                }
            }
        }
コード例 #13
0
        /// <summary>
        /// 创建转置图
        /// </summary>
        /// <param name="copyAction">创建新结点复制属性</param>
        /// <returns></returns>
        public AdjacencyListGraph <T> CreateTransposeGraph(
            Func <AdjacencyVertex <T>, AdjacencyVertex <T> > copyAction = null)
        {
            if (!HasDirection)
            {
                throw new InvalidOperationException("must hasdirection graph");
            }

            if (copyAction == null)
            {
                copyAction = (oldVertex) => new AdjacencyVertex <T>()
                {
                    Key = oldVertex.Key, Identifier = oldVertex.Identifier
                };
            }


            var graph = new AdjacencyListGraph <T>(true);

            var vertexs = new Dictionary <int, AdjacencyVertex <T> >();
            var edges   = new List <AdjacencyEdge <T> >();

            foreach (var item in _adjacencyDictionary.Values)
            {
                var newVertex = copyAction(item);
                vertexs.Add(newVertex.Identifier, newVertex);
            }

            foreach (var item in _adjacencyDictionary.Values)
            {
                edges.AddRange(GetVertexEdge(item)
                               .Select
                                   (o => new AdjacencyEdge <T>(vertexs[o.End.Identifier], vertexs[o.Start.Identifier]))
                               );
            }

            graph.CreatGraph(vertexs.Values, edges);
            return(graph);
        }
コード例 #14
0
        private void DepthFirstSearchVisitStronglyConnected
            (AdjacencyVertex <T> source
            , AdjacencyListGraph <T> graph
            )
        {
            source.Color          = Color.Gray;
            _time                 = _time + 1;
            source.FisrtVisitTime = _time;

            var edges = GetVertexEdge(source);

            //调整
            var newSource = CreateVertex(source);

            graph.AddVertex(newSource);

            foreach (var item in edges)
            {
                var vertex = item.End;

                if (vertex.Color == Color.White)
                {
                    //调整

                    var newVertex = CreateVertex(vertex);
                    graph.AddVertex(newVertex);

                    graph.AddEdge(new AdjacencyEdge <T>(newVertex, newSource));

                    vertex.Predecessor = source;
                    DepthFirstSearchVisitStronglyConnected(vertex, graph);
                }
            }

            source.Color = Color.Black;

            _time = _time + 1;
            source.FinalVisitTime = _time;
        }
コード例 #15
0
        //这个用改造通用版本有点勉强吧!应该没错
        private IList <AdjacencyListGraph <T> > DepthFirstSearchStronglyConnected()
        {
            var stronglyConnectedGraphs = new List <AdjacencyListGraph <T> >();

            foreach (var item in _adjacencyDictionary.Values)
            {
                item.Color       = Color.White;
                item.Predecessor = null;
            }
            _time = 0;

            foreach (var item in _adjacencyDictionary.Values)
            {
                if (item.Color == Color.White)
                {
                    var graph = new AdjacencyListGraph <T>(true);

                    DepthFirstSearchVisitStronglyConnected(item, graph);

                    stronglyConnectedGraphs.Add(graph);
                }
            }
            return(stronglyConnectedGraphs);
        }
コード例 #16
0
 private void Relabel(AdjacencyListGraph <T> graph, AdjacencyVertex <T> vertex)
 {
 }