永夜初晗凝碧天

本博客现已全部转移到新地址,欲获取更多精彩文章,请访问http://acshiryu.github.io/

导航

POJ 1274 The Perfect Stall 解题报告

分类:图论,二分图,最大匹配,匈牙利算法

作者:ACShiryu
时间:2011-7-31

The Perfect Stall

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 11659 Accepted: 5395

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 5
2 2 5
3 2 3 4
2 1 5
3 1 2 5
1 2 

Sample Output

4

题目大意就是求二分图的最大匹配,算得上是基础题,直接运用匈牙利算法可以求解,关于匈牙利算法昨天找了一天资料,看了无数ppt都没有搞懂,那些讲解都太抽象了,直接文字表述,连个图都没有,现在也只是对该算法一知半解。匈牙利算法的思想说白了就是要你从二分图中找出一条路径来,让路径的起点和终点都是还没有匹配过的点,并且路径经过的连线是一条没被匹配、一条已经匹配过,再下一条又没匹配这样交替地出现。找到这样的路径后,显然路径里没被匹配的连线比已经匹配了的连线多一条,于是修改匹配图,把路径里所有匹配过的连线去掉匹配关系,把没有匹配的连线变成匹配的,这样匹配数就比原来多1个。不断执行上述操作,直到找不到这样的路径为止。(传自Matrix67大牛的博客

第一次做,刚开始不懂,看了nocow的代码后,自己当CPU运行了一遍,知道了大概,直接套模板把这题给AC了

参考代码:

 1 #include<iostream>
2 #include<cstdlib>
3 #include<cstdio>
4 #include<cstring>
5 #include<algorithm>
6 #include<cmath>
7 using namespace std;
8 bool map[201][201], vis[201] ; //map保存两点间是否有边,vis保存每次操作后该数是否操作过
9 int link[201] ; //link保存改点连接的另一点的序号
10 int m , n ;
11 bool find ( int k )
12 {//对k寻找匹配,如果找到就记录匹配,并返回true,否则返回false
13 int i , j ;
14 for ( i = 1 ; i <= n ; i ++ )
15 {//对所有节点遍历一遍,寻找没有访问过并且与i连同的点
16 if ( map [k][i] ==true && ! vis[i] )
17 {
18 vis [i] = true ; //记录改点以被访问
19 if ( link [i] == 0 || find ( link [i] ) )
20 {//如果该点还未与其他点匹配,或还能找到其他点能与该点匹配的点j进行匹配,即存在增广路
21 link [ i ] = k ; //将i与k进行匹配
22 return true;
23 }
24 }
25 }
26 return false;
27 }
28 int main()
29 {
30 while ( cin >> m >> n )
31 {//初始化,接受数据的输入
32 memset ( map , false , sizeof ( map ) ) ;
33 memset ( link , 0 , sizeof ( link ) ) ;
34 int i , j ;
35 for ( i = 1 ; i <= m ; i ++ )
36 {
37 int s ;
38 cin >> s ;
39 for ( j = 0 ; j < s ; j ++ )
40 {
41 int k ;
42 cin >> k ;
43 map [i][k] = true ;
44 }
45 }
46
47 int ans = 0 ; //最大匹配数
48 for ( i = 1 ; i <= m ; i ++ )
49 {
50 memset ( vis , false , sizeof ( vis ) ) ;//对所有数据都初始为0,表明数据还没有试探
51 if ( find ( i ) ) //如果对i找到一个匹配
52 ans ++ ;
53 }
54 cout<<ans<<endl;
55 }
56 return 0;
57 }

  

posted on 2011-07-31 17:09  ACShiryu  阅读(1190)  评论(0编辑  收藏  举报