填报志愿(codevs 2930)

题目描述 Description

    高考已经结束,而志愿填报正在进行中~

    吴校长的学校里有n位同学,每位同学有ki个愿意去的大学。而在吴老师的省份中,有m所大学有招生名额。根据往年的经验,对于每所大学(编号为ci),学校中最多只会有一人考上。因此为了避免志愿冲突,每年吴校长都要安排老师对同学们的志愿进行调整。

    今年吴校长找到了你来帮忙,请你编程计算,在不冲突的情况下,最多能有多少同学顺利填报志愿,填报志愿的方案又是怎样的。

输入描述 Input Description

    第一行,一个数n。

    接下来的n行,每行的第一个数为ki,接下来有ki个数,表示第i个同学愿意去的大学的编号。

    下一行,一个数m。 

    下一行,m个数,为m个大学的编号。保证大学编号递增。

输出描述 Output Description

    第一行,一个数,为在不冲突的情况下,最多能有多少同学顺利填报志愿。

    接下来的若干行,输出填报志愿的方案。每行两个数,第一个数为学生编号,第二个数为大学编号,以空格隔开。若有多种可行方案,输出字典序最小的一种。

样例输入 Sample Input

3

2 1 2

3 2 4 5

2 2 3

5

1 3 4 5 6

样例输出 Sample Output

3

1 1

2 4

3 3

数据范围及提示 Data Size & Hint

0<n<=1000,0<ki<=20,0<m<=2000,学生的编号为1~n,大学的编号为1~5000。同学愿意去的大学不一定招生。

#include<cstdio>
#include<iostream>
#include<cstring>
#define M 5010
#define N 1010
using namespace std;
int line[N][M],used[M],belong[M],vis[M],sch[M],n,m;
int find(int x)
{
    for(int i=1;i<=m;i++)
      if(line[x][i]&&!used[i]&&sch[i])
      {
          used[i]=1;
          if(!belong[i]||find(belong[i]))
          {
              belong[i]=x;
              return 1;
        }
      }
    return 0;
}
int main()
{
    scanf("%d",&n);
    int x,y;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        for(int j=1;j<=x;j++)
        {
            scanf("%d",&y);
            line[i][y]=1;
        }
    }
    int e;
    scanf("%d",&e);
    for(int i=1;i<=e;i++)
    {
        scanf("%d",&x);
        sch[x]=1;
        m=max(m,x);
    }
    int tot=0;
    for(int i=1;i<=n;i++)
    {
        memset(used,0,sizeof(used));
        if(find(i))tot++;
    }
    printf("%d",tot);
    return 0;
}
View Code

 

posted @ 2016-07-06 11:12  karles~  阅读(188)  评论(0编辑  收藏  举报