您的位置:首页 > 其它

二分图最大匹配 匈牙利算法 (自己写的模板)

2009-04-30 21:09 274 查看
    以前做二分图最大匹配的时候,都是用别人的模板。今天认真的看了《实用算法分析与设计》关于这个的介绍,并自己写了个模板,感觉从中又学到了好多以前没弄清楚的东西。

//二分图最大匹配  匈牙利算法
//2009.4.30

#include<stdio.h>
#include<string.h>

const int max_v = 500;   //顶点数的上限,注:这里的二分图左右两边顶点个数相等
const int max_e = 10000;  //边数的上限

//边的类型记录
//该边记录的是(x,y) , next指针指向x引出的下一条边的序号
typedef struct
{
int x;
int y;
int next;
}edge;

//二分图的边表
edge arr[max_e];

//first[i]是顶点i引出的首条边的序号
int first[max_v];

//记录匹配信息
//link[i]=0 表示i为未盖点
//link[i]=j 表示(j,i)是匹配边  注:开始就是这里没有看出来,导致好久没看懂
int link[max_v];

//记录使用情况的标志数组
bool used[max_v];

int m,n,index;

//将(x,y)插入到二分图中
void add(int x,int y)
{
index++;
arr[index].x = x;
arr[index].y = y;
arr[index].next = first[x];
first[x] = index;
}

//这里并不是从未盖的x一边搜索y一边,再在y一边搜索x; 而是巧妙的将这两次合并再一次
//具体的理解参照书上的定理和证明,当然那样也可以,不过没这个好
int find(int s)
{
int temp = first[s];

while(temp != -1)
{
if(used[arr[temp].y] == false)
{
used[arr[temp].y] = true;
if(link[arr[temp].y] == 0 || find(link[arr[temp].y]) == 1) //这里的理解比较重要
{
link[arr[temp].y] = s;
return 1;
}
}
temp = arr[temp].next;
}
return 0;
}

int main()
{
int i,x,y;
int count;
while(scanf("%d%d",&n,&m)!=EOF)
{
//初始化
memset(first,-1,sizeof(first));
index = 0;
//读入边信息
for(i = 1;i <= m;i++)
{
scanf("%d%d",&x,&y);
add(x+1,y+1);
}
memset(link,0,sizeof(link));
//二分匹配
for(i = 1 ; i <= n;i++)
{
memset(used,false,sizeof(used));
find(i);
}
//统计结果,并打印结果
printf("/n");
count=0;
for(i = 1;i <= n;i++)
if(link[i] != 0)
{
count++;
printf("%d %d/n",link[i],i);
}
printf("max_match = %d/n",count);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 struct