题目大意:有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;
}
大一时候写的,从网易博客移过来~