匈牙利算法是求二分图的最大匹配的一种算法,它的根据就是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(in