HDU 1083&&POJ 1469解题报告

来源:互联网 发布:手机怎么搜淘宝店铺号 编辑:程序博客网 时间:2024/05/29 14:31

Courses

                                 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
                                                           Total Submission(s): 4034    Accepted Submission(s): 1928


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:
 

Sample Input
23 33 1 2 32 1 21 13 32 1 32 1 31 1
 

Sample Output
YESNO
 

Source
Southeastern Europe 2000
 

Recommend
We have carefully selected several similar problems for you:  1068 2444 2063 1150 1281 
 
       
       这道题是比较典型的二分图匹配,而且建图也比较好建。这道题直接给出了课程和学生这两个集合,而且这两个集合内部相互独立。学生选课构成一种关系。因此我们在学生与课程这两个集合的对应点之间进行连边操作。边代表的含义是学生选课。在建图的时候一定要清楚图的点集和边集分别代表的含义。这一点很重要。而本题比较常规,因此该重要性体现不明显。还有一点需要注意的是建图的时候要明确自己构建的二分图是有向图还是无向图,因为是否有向将会影响到最终二分图的匹配数。因此需要格外注意。还需要判断能否构建无向图,是否必须构建无向图等。
       这道题由于学生与课程之间的关系存在选与被选的关系,这个关系是相互的。因此是可以构建无向图的。当然我们也可以构建有向图。
       下面是二分图最大匹配的代码:
        
#include<cstdio>#include<iostream>#include<algorithm>#include<vector>#include<cstring>#define pb push_back#define CLR(x) memset(x,0,sizeof(x))#define __CLR(x) memset(x,-1,sizeof(x))using namespace std;int a[310],b[310],vis[310],match[310],p,n;vector<int>G[505];bool dfs(int u){    for(int i=0; i<G[u].size(); i++)    {        int t=G[u][i];        if(!vis[t])        {            vis[t]=1;            if(match[t]==-1||dfs(match[t]))            {                match[t]=u;                return true;            }        }    }    return false;}int main(){    //ios_base::sync_with_stdio(0);    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&p,&n);        bool flag=1;        for(int i=1; i<=p; i++)        {            int k;            scanf("%d",&k);            if(!k) flag=0;            for(int j=0; j<k; j++)            {                int v;                scanf("%d",&v);                G[i].pb(v);                //G[v].pb(i);         //如果把这句话加上就错了。我们建图相当于之保留了二分图中一个集合中的所有点。而只需保留另一个集合中与之相连的点的标号即可。如果用邻接矩阵存储,则邻接矩阵的行列分别代表的是两个集合,所以这样的边是有向的。           //当然如果想建立无向图,可以在同一个图中存储两个不同的点集。只要保证标号不同即可。           //如:G[i].pb(p+v); G[p+v].pb(i);            }        }        if(flag)        {            int num=0;            __CLR(match);            for(int i=1; i<=p; i++)            {                CLR(vis);                if(dfs(i))                    num++;            }            if(num==p) printf("YES\n");            else printf("NO\n");        }        else            printf("NO\n");        for(int i=0; i<505; i++)            G[i].clear();    }}

0 0
原创粉丝点击