POJ1274 — 二分图匹配模板题

来源:互联网 发布:淘宝手机流量互刷软件 编辑:程序博客网 时间:2024/06/16 00:28

                                                         The Perfect Stall
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 22876 Accepted: 10190

Description

Farmer John completed his new barn just last week, complete with all the latest milking technology. Unfortunately, due to engineering problems, all the stalls in the new barn are different. For the first week, Farmer John randomly assigned cows to stalls, but it quickly became clear that any given cow was only willing to produce milk in certain stalls. For the last week, Farmer John has been collecting data on which cows are willing to produce milk in which stalls. A stall may be only assigned to one cow, and, of course, a cow may be only assigned to one stall.
Given the preferences of the cows, compute the maximum number of milk-producing assignments of cows to stalls that is possible.

Input

The input includes several cases. For each case, the first line contains two integers, N (0 <= N <= 200) and M (0 <= M <= 200). N is the number of cows that Farmer John has and M is the number of stalls in the new barn. Each of the following N lines corresponds to a single cow. The first integer (Si) on the line is the number of stalls that the cow is willing to produce milk in (0 <= Si <= M). The subsequent Si integers on that line are the stalls in which that cow is willing to produce milk. The stall numbers will be integers in the range (1..M), and no stall will be listed twice for a given cow.

Output

For each case, output a single line with a single integer, the maximum number of milk-producing stall assignments that can be made.

Sample Input

5 52 2 53 2 3 42 1 53 1 2 51 2 

Sample Output

4

这道题是一个模板题去寻找最大匹配,最大匹配就是找出两两匹配的最多的情况。还有一种叫最优匹配,就是保证全部点都匹配上了,最优匹配存在的时候必定也是最大匹配。不是所有的二分图都有最优匹配的,但是最大匹配还是会有的。

这道题我是拿别人DFS的模板过的,但是有评测说过,DFS在数据小的时候效率会很低,一直到大数据的时候,才能和BFS的效率持平,所以BFS其实更好,不过也更难懂,代码更长。

其实研究了一下DFS的模板,以前有的问题也是这种办法的,就是如果遇到匹配点重复的,向前找,看看这个一开始的匹配这个匹配点的点(当做是父亲结点吧)是否可以去匹配其他的点,如果可以就让他匹配其他点,然后自己就匹配这个匹配点,否则的话,就放弃这个匹配点,因为这个匹配点的父亲结点无法匹配其他点了,那么他跟这个匹配点匹配是一种情况,让计数+1,而你和这个匹配点匹配也就是让计数+1罢了,都一样,那就懒得去改这个点了,其实改不改都可以吧。就是改的话程序就不好写,感觉根本写不出来

代码如下:(我wa了一次,因为我忘记给这个图去初始化了。。。)

#include<cstdio>#include<queue>#include<vector>#include<iostream>#include<map>#include<cmath>#include<cstring>#include<algorithm>#include<set>using namespace std;#define N 202  int useif[N];   //记录y中节点是否使用 0表示没有访问过,1为访问过  int link[N];   //记录当前与y节点相连的x的节点  int mat[N][N]; //记录连接x和y的边,如果i和j之间有边则为1,否则为0  int gn,gm;    //二分图中x和y中点的数目  int can(int t)  {      int i;      for(i=1;i<=gm;i++)      {         if(useif[i]==0 && mat[t][i])         {             useif[i]=1;             if(link[i]==-1 || can(link[i]))             {                link[i]=t;                return 1;             }         }      }      return 0;  }  int MaxMatch()  {      int i,num;      num=0;      memset(link,0xff,sizeof(link));      for(i=1;i<=gn;i++)      {        memset(useif,0,sizeof(useif));         if(can(i)) num++;      }      return num;  }  int main(void){//freopen("in.txt","r",stdin);int i,t,tmp;while(scanf("%d%d",&gn,&gm)!=EOF){memset(mat,0,sizeof(mat));for(i=1;i<=gn;i++){scanf("%d",&t);while(t--){scanf("%d",&tmp);mat[i][tmp]=1;}}t=MaxMatch();printf("%d\n",t);//for(i=1;i<=gn;i++)//printf("%d ",link[i]);}return 0;}

自己手写一遍题目给出的例子,就可以明白这段代码到底想干嘛了奋斗



0 0