您的位置:首页 > 其它

Poj1274二分图最大匹配(匈牙利算法)

2016-02-25 09:14 218 查看
题目大意:有N头奶牛,M个产奶的棚子,每头奶牛都有自己想去产奶的几个棚子,问可以产生的最大匹配数。

数据:
Sample Input


5 5                           N M

2 2 5        第一头: t m2 m5

3 2 3 4     第二头: t m2 m3 m4

2 1 5        第三头:…..

3 1 2 5     第四头:…..

1 2           第五头:…..

Sample Output

4
解题思路:将奶牛看成N集合,棚子看成M集合

1,对于N集合中一个未匹配的节点i,寻找它的每条关联边,如果它的边上的另一个节点j还没匹配则表明找到了一个匹配,直接转步骤4;

2,假如节点i它边上的另一个节点j已经匹配,那么就转向跟j匹配的节点,也就是它的前驱,假设是pre[j],然后再对pre[j]重复1,2的步骤,即寻找增广路径.

3,假如我们在1,2步过程中找到一条增广路, 那么修改各自对应的匹配点,转步骤4,若无增广路, 则退出.

4,匹配数+1;

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int Max = 201;
int N,M;
int arc[Max][Max];        //用邻接矩阵保存图
int visit[Max];           //访问标志
int pre[Max];             //匹配边集,前驱

int dfs(int i)
{
for(int j = 1; j <= M; j++)
{
if(visit[j] == 0 && arc[i][j] == 1)  //搜索所有与i相邻的未访问点
{
visit[j] = 1;
if(pre[j] == 0 || dfs(pre[j]))   //若j的前驱是未盖点或者存在由j的前驱出发的增广路径,则存在匹配边,返回1;
{
pre[j] = i;
return 1;
}
}
}
return 0;
}

int main()
{
int t,i;
while(scanf("%d %d",&N,&M)!=EOF)
{
memset(arc,0,sizeof(arc));   //初始化
memset(pre,0,sizeof(pre));
for(i = 1; i <= N; i++)
{
scanf("%d",&t);
for(int j = 1; j <= t; j++)
{
int x;
scanf("%d",&x);
arc[i][x] = 1;
}
}

int ans = 0; //匹配边数
for(i = 1; i <= N; i++)
{
memset(visit,0,sizeof(visit));
if(dfs(i))       //若结点i被匹配边覆盖,则匹配边数+1
ans++;
}
printf("%d\n",ans);
}
return 0;
}


大一时候写的,从网易博客移过来~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息