codevs2930 填报志愿-还是二分图

来源:互联网 发布:快剪试验数据 编辑:程序博客网 时间:2024/04/27 22:47





2930 填报志愿

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

    吴校长的学校里有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。同学愿意去的大学不一定招生hh


题目有问题,评测不需要提交匹配方案。

代码:这是带方案数的代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std; 
struct node{
int to ,next;
}edge[200009];
int n,m,cnt=0,head[1009];


int sum=0,match[5009],used[5009],have[5009],mat_stu[1009];
void add(int u,int v){
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
int dfs(int u){
int i;
for(int i=head[u];i!=-1;i=edge[i].next){
if(have[edge[i].to]&&!used[edge[i].to]){
used[edge[i].to]=1;
if(match[edge[i].to]==0||dfs(match[edge[i].to])){
match[edge[i].to]=u;
mat_stu[u]=edge[i].to;
return 1;
}
}
}
return 0;
}
int main(){
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
int i,j,k;
scanf("%d",&n);

memset(head,-1,sizeof(head));
for(i=1;i<=n;i++){
  int t,x[20]={0};
  scanf("%d",&t);
  for(j=1;j<=t;j++)
   scanf("%d",&x[j]);//排序,为了找方案的最小字典序。
  sort(x+1,x+t+1);
  for(j=t;j>=1;j--)      
add(i,x[j]);
}


scanf("%d",&m);
for(int i=1;i<=m;i++){
int x;
scanf("%d",&x);
have[x]=1;
}
sum=0;
for(i=1;i<=n;i++){
memset(used,0,sizeof(used));
if(dfs(i))sum++;
}


    printf("%d\n",sum);
for(int i=1;i<=n;i++){
if (mat_stu[i]){
int school=mat_stu[i];
if(match[school]==i)
 printf("%d %d\n",i,school);

}
}



return 0;
}

0 0
原创粉丝点击