void FillMaximalMatching(BipartiteGraphMatching <T> matching)
        {
            GetMaximalMatchingFSet fSet = new GetMaximalMatchingFSet(Data.VSize);

            do
            {
                fSet.Clear();
                var freeUVertexList = Data.GetUVertexList().Where(x => !IsMatchedVertex(x));
                foreach (var uVertex in freeUVertexList)
                {
                    Color bfsColor = Color.CreateColor();
                    DoBFSearch(uVertex, (x, y) =>
                               IsMatchedEdge(x, y) ? Data.IsVVertex(x) : Data.IsUVertex(x)
                               , (x, y) =>
                               Data.UpdateEdgeData(x, y, edgeData => edgeData.WithColor(bfsColor))
                               , x => {
                        if (Data.IsVVertex(x) && !IsMatchedVertex(x))
                        {
                            if (IsInFSet(x))
                            {
                                fSet.UpdateItem(x.GetData <GetMaximalMatchingVertexInFSetData>().ItemIndex, new GetMaximalMatchingFSetItem(x, bfsColor));
                            }
                            else
                            {
                                int itemIndex = fSet.AddItem(new GetMaximalMatchingFSetItem(x, bfsColor));
                                x.Data        = new GetMaximalMatchingVertexInFSetData(itemIndex);
                            }
                            return(false);
                        }
                        return(true);
                    });
                }
                foreach (var fSetItem in fSet)
                {
                    DoDFSearch(fSetItem.Vertex, (x, y) => Data.GetEdgeData(x, y).Color == fSetItem.BfsColor
                               , (x, y) => {
                        var uVertex = matching.Data.GetUVertex(Data.GetUVertex(x, y).Handle);
                        var vVertex = matching.Data.GetVVertex(Data.GetVVertex(x, y).Handle);
                        if (IsMatchedEdge(x, y))
                        {
                            Data.GetEdgeData(x, y).WithData(null);
                            matching.DeleteEdge(uVertex, vVertex);
                        }
                        else
                        {
                            Data.UpdateEdgeData(x, y, edgeData => edgeData.WithData(new GetMaximalMatchingMatchedData()));
                            matching.CreateEdge(uVertex, vVertex);
                        }
                    }, x => {
                        bool stopSearch = Data.IsUVertex(x) && !IsMatchedVertex(x);
                        x.Data          = new GetMaximalMatchingMatchedData();
                        return(stopSearch ? false : true);
                    });
                }
            }while(fSet.Size != 0);
            ClearData(true, true);
        }
        BipartiteGraphMatching <T> GetMaximalMatchingCore()
        {
            BipartiteGraphMatching <T> matching = Clone <BipartiteGraphMatching <T> >(false);

            if (Size != 0)
            {
                FillMaximalMatching(matching);
            }
            return(matching);
        }
        public BipartiteGraphMatching <T> GetAssignmentMatching()
        {
            if (Data.USize != Data.VSize || Properties.IsNegativeWeighted || !IsComplete())
            {
                throw new InvalidOperationException();
            }
            BipartiteGraphMatching <T> graph = Clone <BipartiteGraphMatching <T> >(false);
            Func <int, int, double, EdgeData, EdgeData> func1 = (row, column, minVal, x) => {
                var edgeData = x.WithWeight(x.Weight - minVal);
                if (MathUtils.AreEqual(edgeData.Weight, 0))
                {
                    graph.EnsureEdge(column, row, x.Weight);
                }
                return(edgeData);
            };
            Func <int, int, double, EdgeData, EdgeData> func2 = (row, column, minVal, x) => {
                var edgeData = x.WithWeight(x.Weight + minVal);
                if (!MathUtils.AreEqual(edgeData.Weight, 0))
                {
                    graph.EnsureNoEdge(column, row);
                }
                return(edgeData);
            };
            RectMatrix <EdgeData, Color> matrix = Data.Matrix.Clone();
            int rowCount = matrix.Size.RowCount;

            for (int n = 0; n < rowCount; n++)
            {
                double minVal = matrix.GetRowItemList(n).Select(x => x.Weight).Min();
                matrix.TranslateRow(n, func1, minVal);
            }
            if (graph.IsPerfect())
            {
                return(graph);
            }
            int columnCount = matrix.Size.ColumnCount;

            for (int n = 0; n < columnCount; n++)
            {
                double minVal = matrix.GetColumnItemList(n).Select(x => x.Weight).Min();
                matrix.TranslateColumn(n, func1, minVal);
            }
            if (graph.IsPerfect())
            {
                return(graph);
            }
            while (true)
            {
                var matching = graph.GetMaximalMatchingCore();
                if (matching.IsPerfect())
                {
                    return(CloneWithEdges(matching));
                }
                Color color1 = Color.CreateColor();
                matching.Data.GetVVertexList()
                .Where(x => x.Degree != 0)
                .ForEach(x => matrix.RowAttributes[x.Handle] = color1);
                Color color2 = Color.CreateColor();
                matrix.TranslateRowAttributes((row, rowColor) => rowColor != color1, x => color2);
                matrix.ForEach((row, column, rowColor, columnColor, x) => rowColor == color2 && MathUtils.AreEqual(x.Weight, 0), (row, column, x) => {
                    matrix.ColumnAttributes[column] = color2;
                    for (int n = 0; n < matrix.Size.RowCount; n++)
                    {
                        if (matching.AreVerticesAdjacent(column, n))
                        {
                            matrix.RowAttributes[n] = color2;
                        }
                    }
                });
                Color color3 = Color.CreateColor();
                matrix.TranslateColumnAttributes((column, columnColor) => columnColor == color2, x => color3);
                matrix.TranslateRowAttributes((row, rowColor) => rowColor != color2, x => color3);
                double minValue = matrix.GetItems((row, column, rowColor, columnColor, x) => rowColor != color3 && columnColor != color3).Select(x => x.Weight).Min();
                matrix.Translate((row, column, rowColor, columnColor, x) => rowColor != color3 && columnColor != color3, func1, minValue);
                matrix.Translate((row, column, rowColor, columnColor, x) => rowColor == color3 && columnColor == color3, func2, minValue);
            }
        }