Girls and Boys
Time Limit: 10 Seconds Memory Limit: 32768 KB
the second year of the university somebody started a study on the romantic relations between the students. The relation ��romantically involved�� is defined between one girl and one boy. For the study reasons it is necessary to find out the maximum set satisfying the condition: there are no two students in the set who have been ��romantically involved��. The result of the program is the number of students in such a set.
The input contains several data sets in text format. Each data set represents one set of subjects of the study, with the following description:
the number of students
the description of each student, in the following format
student_identifier:(number_of_romantic_relations) student_identifier1 student_identifier2 student_identifier3 …
or
student_identifier:(0)
The student_identifier is an integer number between 0 and n-1, for n subjects.
For each given data set, the program should write to standard output a line containing the result.
An example is given in Figure 1.
Input
7
0: (3) 4 5 6
1: (2) 4 6
2: (0)
3: (0)
4: (2) 0 1
5: (1) 0
6: (2) 0 1
3
0: (2) 1 2
1: (1) 0
2: (1) 0
Output
5
2
问题分析
二分图定义:如果一个图的所有顶点可以被分为X和Y两个集合并且所有边的两个顶点恰好一个属于集合X,另一个属于集合Y,即每个集合内的顶点没有边相连,那么此图就是二分图。
二分图最大独立集 = 顶点数 - 最大匹配数
如果二分图有n个点,那么最多找到n/2条增广路径。(如果当前匹配方案下再也找不到增广路,那么当前匹配就是最大匹配)如果图中共有m条边,那么每找一条增广路径最多把所有边遍历一遍,所花时间为m,所以总的时间复杂度为O(n*m)。
好,接下来是AC code(^_^)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 503;
int e[N][N],match[N],n;
int book[N];
int dfs(int u)
{
for(int i = 0; i < n; i++)
{
if(book[i]==0&&e[u][i]==1)
{
book[i] = 1; //标记点i已访问过
//如果点i未被配对或者找到了新的配对
if(match[i]==-1||dfs(match[i]))
{
//更新配对关系
match[i] = u;
return 1;
}
}
}
return 0;
}
int main()
{
// freopen("in.txt","r",stdin);
while(~scanf("%d",&n))
{
memset(e,0,sizeof e);
memset(match,-1,sizeof match);
for(int i = 0; i < n; i++)
{
int k,cnt;
scanf("%d: (%d)",&k,&cnt);
for(int j = 0; j < cnt; j++)
{
int x;
scanf("%d",&x);
e[i][x] = 1;
}
}
int ans = 0;
for(int i = 0; i < n; i++)
{
memset(book,0,sizeof(book));
if(dfs(i)) //寻找增广路,如果找到,配对数加一(增广路就是一条路径的七点和终点都是未配对的点)
ans++;
}
printf("%d\n",n-ans/2);//除2是因为算了两遍
}
return 0;
}