匈牙利算法(C#)实现

原创 2006年05月24日 12:42:00

    匈牙利算法是求二分图的最大匹配的一种算法,它的根据就是Hall定理中充分性证明中的思想。( 卢开澄,卢化明. 图论及其应用.清华大学出版社[M]1995.)

使用举例:要给定条件(二分图)和初始匹配.

int[,] TestMaxArray = new int[5, 5]{
                             {  1, 1,-1, -1, -1 },
                             { -1, 1, 1, -1, -1 },
                             { -1, 1,-1, -1,  1 },
                             { -1,-1, 1, -1, -1 },
                             { -1,-1, 1,  1,  1 }};
int[,] GivenArray = new int[5, 5]{
                             {  1, 0, 0,  0, 0 },
                             {  0, 0, 0,  0, 0 },
                             {  0, 0, 0,  0, 1 },
                             {  0, 0, 0,  0, 0 },
                             {  0, 0, 1,  0, 2 }};
MaxMatch testtest = new MaxMatch(TestMaxArray, GivenArray);//实例化
int [,] resultArray = testtest.resultArray();//结果  

下面是实现代码: MaxMatch.csusing System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace MaxMatch
{
    /// <summary>
    /// The values of Array must be -1 or 1 or 0
    /// </summary>
    public class MaxMatch
    {
        private int[,] OriginData;
        private int[,] GivenMatch;
        private int cn, rn;
        private ArrayList OldIndexOfV1, OldIndexOfV2;
        private int[] SequencedIndexOfV2, TV1;

        public MaxMatch(int[,] OriginData, int[,] GivenMatch)//, int cn, int rn)
        {
            this.OriginData = OriginData;
            this.GivenMatch = GivenMatch;
            GivenMatch = this.GivenMatch;
            this.cn = OriginData.GetLength(1);
            this.rn = OriginData.GetLength(0);

            this.GivenMatch = new int[rn, cn];
            for (int i = 0; i < rn; i++)
            {
                for (int j = 0; j < cn; j++)
                {
                    int bTemp = 0;
                    bTemp = OriginData[i, j];
                    if (bTemp == -1)
                    {
                        this.GivenMatch[i, j] = bTemp;
                    }
                    else
                    {
                        this.GivenMatch[i, j] = GivenMatch[i, j];
                    }
                }
            }

            OldIndexOfV1 = new ArrayList();
            OldIndexOfV2 = new ArrayList();
            SequencedIndexOfV2 = new int[cn];
            TV1 = new int[cn];
        }

        /*
         * 是否饱和
         */
        bool boolDataFull()
        {
            bool booloneline = false;
            for (int i = 0; i < rn; i++)
            {
                booloneline = false;
                for (int j = 0; j < cn; j++)
                {
                    if (GivenMatch[i, j] == 1)
                    {
                        booloneline = true;
                        break;
                    }
                }// for j
                if (booloneline == false)
                {
                    return false;
                }
            }// for i
            return true;
        }

        /*
         * 在{X}中找一非饱和点,如果X饱和则返回-1;
         */
        int SearchNotFullIndexOfX()
        {
            bool booloneline = false;
            for (int i = 0; i < rn; i++)
            {
                booloneline = false;
                for (int j = 0; j < cn; j++)
                {
                    //Console.Write(GivenMatch[i, j].ToString());
                    if (GivenMatch[i, j] == 1)
                    {
                        booloneline = true;
                        break;
                    }
                }// for j
                if (booloneline == false)
                {
                    return i;
                }
            }// for i
            return -1;
        }

        /*
         * 两个等长数组值是否相等
         */
        bool IsTV1EqualV2(int[] TV11, int[] V2)
        {
            string str1 = "";
            string str2 = "";
            for (int j = 0; j < cn; j++)
            {
                str1 += TV11[j];
                str2 += V2[j];
            }

            if (str1 == str2)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /*
         * 找出一顶点在V1的邻接点集合T(V1)但不在V2中.
         * 传入两个等长一维数组 值为0、1。如果找不到就返回 -1
         */
        int InTV1NotInV2(int[] TV11, int[] V2)
        {
            for (int j = 0; j < cn; j++)
            {
                if (TV11[j] == 1 && V2[j] == 0)
                {
                    return j;
                }
            }// for j
            return -1;
        }

        /*
         * 判断y点是否饱和,饱和取得关联的x的序号,否则直接返回 -1。
         * 传入参数为:y点对应的序号
         */
        int IndexOfXMakeYFull(int indexofy)
        {
            for (int i = 0; i < rn; i++)
            {
                if (GivenMatch[i, indexofy] == 1)
                {
                    return i;
                }
            }// for i
            return -1;
        }

        void ExpandOldIndexOfV1(int indexofx)
        {
            OldIndexOfV1.Add(indexofx);
            for (int j = 0; j < cn; j++)
            {
                if (OriginData[indexofx, j] == 1)
                {
                    TV1[j] = 1;
                }
            }
        }

        void ExpandOldIndexOfV2(int indexofy)
        {
            OldIndexOfV2.Add(indexofy);
            SequencedIndexOfV2[indexofy] = 1;
        }

        void ExpandGivenMatch()
        {
            int[] V1index = (int[])OldIndexOfV1.ToArray(typeof(int));
            int[] V2index = (int[])OldIndexOfV2.ToArray(typeof(int));

            for (int i = 0; i < V1index.Length - 1; i++)
            {
                GivenMatch[V1index[i], V2index[i]] = 1;
                GivenMatch[V1index[i + 1], V2index[i]] = 0;
            }// for i
            if (V2index.Length == V1index.Length)
            {
                int i = V2index.Length - 1;
                GivenMatch[V1index[i], V2index[i]] = 1;
            }
        }

        void MaxMatching()
        {
            bool boolfull = false;
            bool boolhaveexpanded = true;
            bool booladdx = true;
            while (boolhaveexpanded == true)
            {
                boolhaveexpanded = false;
                booladdx = true;
                boolfull = boolDataFull();
                if (boolfull == true)
                {
                    return;
                }
                else
                {
                    for (int i = 0; i < cn; i++)
                    {
                        SequencedIndexOfV2[i] = 0;
                        this.TV1[i] = 0;
                    }
                    OldIndexOfV1.Clear();
                    OldIndexOfV2.Clear();

                    int notfullindexofx = SearchNotFullIndexOfX();
                    ExpandOldIndexOfV1(notfullindexofx);

                    while (booladdx == true)
                    {
                        booladdx = false;
                        bool boolequal = IsTV1EqualV2(this.TV1, SequencedIndexOfV2);
                        if (boolequal == true)
                        {
                            return;
                        }
                        else
                        {
                            int iy = InTV1NotInV2(this.TV1, SequencedIndexOfV2);
                            ExpandOldIndexOfV2(iy);

                            int ix = IndexOfXMakeYFull(iy);
                            if (ix != -1)
                            {
                                ExpandOldIndexOfV1(ix);
                                booladdx = true;
                                boolhaveexpanded = true;
                            }
                            else
                            {
                                ExpandGivenMatch();
                                boolhaveexpanded = true;
                                //break;
                            }
                        }
                    }//while booladdx == true                             
                }//if   boolfull == true            
            }//while boolhaveexpanded == true
            //showdata();
        }

       

        #region Check the Array's values
        void Checked()
        {
            if (OriginData.GetLength(0) != GivenMatch.GetLength(0))
            {
                throw new Exception("The first dimension of " + OriginData +
                    " should be equal to the first dinesion of" + GivenMatch);
            }
            if (OriginData.GetLength(1) != GivenMatch.GetLength(1))
            {
                throw new Exception("The first dimension of " + OriginData +
                    " should be equal to the first dinesion of" + GivenMatch);
            }
            for (int i = 0; i < OriginData.GetLength(0); i++)
            {
                for (int j = 0; j < OriginData.GetLength(1); j++)
                {
                    if (OriginData[i, j] > 1 || OriginData[i, j] < -1)
                    {
                        throw new Exception("Each value of " + OriginData +
                            " must be -1 or 0 or 1 ");
                    }
                    if (GivenMatch[i, j] > 1 || GivenMatch[i, j] < -1)
                    {
                        throw new Exception("Each value of " + GivenMatch +
                            " must be -1 or 0 or 1 ");
                    }
                }
            }
        }

        #endregion
        public int[,] resultArray()
        {
            Checked();
            MaxMatching();
            return GivenMatch;
        }
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

匈牙利算法(C#版)

  • 2009-11-16 15:51
  • 13KB
  • 下载

匈牙利算法的C++实现

这篇文章最初发表在http://blog.csdn.net/j56754gefge/article/details/40793633,均是我原创,转载请注明出处!     Hungari...

匈牙利算法java实现

匈牙利算法的一个实现

#include void main() { int T,m,n,i,j,k,M[100][100],N[101][101],temp,col,row,c,r; char F[101...

(Java实现) HDOJ 2063 过山车 匈牙利算法

匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名。匈牙利算法是基于Hall定理中充分性证明的思想,它是部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最...

匈牙利算法的C++实现(基于OpenCV)

Hungarian Algorithm

二分图匹配匈牙利算法(DFS, BFS两种实现模板)

3个重要结论: 最大匹配数:最大匹配的匹配边的数目 最小点覆盖数:选取最少的点,使任意一条边至少有一个端点被选择 最大独立集:选取最多的点,使任意所选两点均不相连 最小路径覆盖数:对于一个...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)