Courses
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3647 Accepted Submission(s): 1747
Problem Description
Consider a group of N students and P courses. Each student visits zero, one or more than one courses. Your task is to determine whether it is possible to form a committee of exactly P students that satisfies simultaneously the conditions:
. every student in the committee represents a different course (a student can represent a course if he/she visits that course)
. each course has a representative in the committee
Your program should read sets of data from a text file. The first line of the input file contains the number of the data sets. Each data set is presented in the following format:
P N
Count1 Student1 1 Student1 2 ... Student1 Count1
Count2 Student2 1 Student2 2 ... Student2 Count2
......
CountP StudentP 1 StudentP 2 ... StudentP CountP
The first line in each data set contains two positive integers separated by one blank: P (1 <= P <= 100) - the number of courses and N (1 <= N <= 300) - the number of students. The next P lines describe in sequence of the courses . from course 1 to course P, each line describing a course. The description of course i is a line that starts with an integer Count i (0 <= Count i <= N) representing the number of students visiting course i. Next, after a blank, you'll find the Count i students, visiting the course, each two consecutive separated by one blank. Students are numbered with the positive integers from 1 to N.
There are no blank lines between consecutive sets of data. Input data are correct.
The result of the program is on the standard output. For each input data set the program prints on a single line "YES" if it is possible to form a committee and "NO" otherwise. There should not be any leading blanks at the start of the line.
An example of program input and output:
. every student in the committee represents a different course (a student can represent a course if he/she visits that course)
. each course has a representative in the committee
Your program should read sets of data from a text file. The first line of the input file contains the number of the data sets. Each data set is presented in the following format:
P N
Count1 Student1 1 Student1 2 ... Student1 Count1
Count2 Student2 1 Student2 2 ... Student2 Count2
......
CountP StudentP 1 StudentP 2 ... StudentP CountP
The first line in each data set contains two positive integers separated by one blank: P (1 <= P <= 100) - the number of courses and N (1 <= N <= 300) - the number of students. The next P lines describe in sequence of the courses . from course 1 to course P, each line describing a course. The description of course i is a line that starts with an integer Count i (0 <= Count i <= N) representing the number of students visiting course i. Next, after a blank, you'll find the Count i students, visiting the course, each two consecutive separated by one blank. Students are numbered with the positive integers from 1 to N.
There are no blank lines between consecutive sets of data. Input data are correct.
The result of the program is on the standard output. For each input data set the program prints on a single line "YES" if it is possible to form a committee and "NO" otherwise. There should not be any leading blanks at the start of the line.
An example of program input and output:
Sample Input
2 3 3 3 1 2 3 2 1 2 1 1 3 3 2 1 3 2 1 3 1 1
Sample Output
YES NO
Source
Recommend
匈牙利算法模板详解(http://blog.csdn.net/candy20094369/article/details/6680117)
/*===========================================================*\
G为图,M为图中的一个匹配,从X集合到Y集合找一个最大匹配
交互道路:对于G的一个匹配M, G中属于M与不属于M的边交替出现的道路
称为一条交互道路.
可增广道路:设P是关于匹配M的一条交互道路,如果P的两个端点是关于
M的非饱和点,那么称P是一条可增广道路。
\*===========================================================*/
int uN, vN; // uN为集合X的个数, vN为集合Y的个数,要初始化!!!
bool g[MAXN][MAXN]; // g[i][j] 表示xi与yj相连
int xM[MAXN], yM[MAXN]; // 输出量
bool chk[MAXN]; // 辅助量检查某轮y[v]是否被check
bool SearchPath(int u){
int v;
for(v = 0; v < vN; v++)
if(g[u][v] && !chk[v])//取u的临界点集合为Y,并且Y没有被访问过
{
chk[v] = true;
if(yM[v] == -1 || SearchPath(yM[v]))//若Y中有非饱和点(-1),则找到一条增广路径;
//若Y已饱和,则找到在匹配M中的边(x,y),x的集合加到X中,
//延长路径(-1->饱和Y->饱和X->(找非饱和点)),SearchPath(yM[v])找到Y中的一个非饱和点
{
yM[v] = u; xM[u] = v;//进行值更新
return true ;
}
}
return false ;
}
int MaxMatch(){
int u, ret = 0 ;
memset(xM, -1, sizeof (xM));//-1表示为非饱和点
memset(yM, -1, sizeof (yM));//-1表示为非饱和点
for(u = 0; u < uN; u++)
if(xM[u] == -1){// 在集合X中找任一非饱和点进行一次增广路径的查找
memset(chk, false, sizeof (chk));
if(SearchPath(u)) ret++;//如果找到一条增广路径,最大匹配的个数加1
}
return ret;
}
我的ac代码
#include<stdio.h>
#include<string.h>
int p,n,v[500],xm[500],ym[500],map[500][500];
int dfs(int u)
{
int i;
for(i=1;i<=n;i++)
{
if(!v[i]&&map[u][i])
{
v[i]=1;
if(ym[i]==-1||dfs(ym[i]))
{
ym[i]=u;
xm[u]=i;
return 1;
}
}
}
return 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int i,j,k,m,sum=0;
scanf("%d%d",&p,&n);
memset(xm,-1,sizeof(xm));
memset(ym,-1,sizeof(ym));
memset(map,0,sizeof(map));
for(i=1;i<=p;i++)
{
scanf("%d",&m);
while(m--)
{
int a,b;
scanf("%d",&a);
map[i][a]=1;
}
}
for(i=1;i<=p;i++)
{
if(xm[i]==-1)
{
memset(v,0,sizeof(v));
if(dfs(i))
sum++;
}
}
if(sum==p)
printf("YES\n");
else
printf("NO\n");
}
}