HDU 1083:Courses

来源:互联网 发布:如何考环评工程师 知乎 编辑:程序博客网 时间:2024/06/08 15:43

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1083

题目给出P门课程N个学生,然后给出对应选某门课程的学生编号。

每门课程必须要有一个不同的课代表。

一个学生也只能当一门课的课代表。

求图中是否存在这样的匹配。有的话输出YES,否则输出NO

二分图匹配入门题目,感觉题目描述有问题,英文是: every student in the committee represents a different course

every student 是每个学生代表一个不同的课,让我误以为P 和 N最后还要判别相等(害我Wa掉了)。

事实上是只要P门课能选出P个不同的课代表就行了,可能一部分学生不担任课代表。


比如第二组测试数据变成:

3 4

2 1 3

2 1 3

2 1 4

YES


AC代码:

#include <iostream>#include <stdio.h>#include <string.h>using namespace std;int P,N;            ///P门课,N个学生const int maxn = 1000;const int maxm = 100000;int head[maxn];int edgeNumber;struct Edge{    int u;    int v;    int nex;}edge[maxm];void addEdge(int u,int v){    edge[edgeNumber].u = u;    edge[edgeNumber].v = v;    edge[edgeNumber].nex = head[u];    head[u] = edgeNumber++;}int vis[maxn];int match[maxn];bool hungry(int x){    for(int i = head[x]; i != -1; i = edge[i].nex)    {        int y = edge[i].v;        if(vis[y]==0)        {            vis[y] = 1;            if(match[y]==0 || hungry(match[y]))            {                match[y] = x;                match[x] = y;                return true;            }        }    }    return false;}void solve(){    int ans = 0;    memset(match,0,sizeof(match));    for(int i = 1; i <= P; i++)    {        memset(vis,0,sizeof(vis));        if(hungry(i+N))            ans++;    }    if(ans == P)        printf("YES\n");    else        printf("NO\n");}int main(){    int ccount,x;    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&P,&N);        {            edgeNumber = 0;            memset(head,-1,sizeof(head));            for(int i = 1; i <= P; i++)            {                scanf("%d",&ccount);                while(ccount--)                {                    scanf("%d",&x);                    addEdge(x,i+N);                    addEdge(i+N,x);                }            }            solve();        }    }    return 0;}