# 匈牙利算法(C#)实现

997人阅读 评论(0)

匈牙利算法是求二分图的最大匹配的一种算法，它的根据就是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();//结果

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)
{
for (int j = 0; j < cn; j++)
{
if (OriginData[indexofx, j] == 1)
{
TV1[j] = 1;
}
}
}

void ExpandOldIndexOfV2(int 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;
while (boolhaveexpanded == true)
{
boolhaveexpanded = false;
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);

{
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);
boolhaveexpanded = true;
}
else
{
ExpandGivenMatch();
boolhaveexpanded = true;
//break;
}
}
}//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;
}
}
}

0
0

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：3894次
• 积分：69
• 等级：
• 排名：千里之外
• 原创：4篇
• 转载：0篇
• 译文：0篇
• 评论：0条
文章存档
评论排行