计蒜客 填志愿 解题报告

来源:互联网 发布:mac可以玩的国内网游 编辑:程序博客网 时间:2024/04/25 23:27

有一个国家采取全民教育、自主选择的方式,尽可能多的将高中毕业的学生安排进大学进行学习(国家只会安排学生进入他们希望进入的大学,而不会让他们进入自己不想去的学校)。但是,在此之前,所有的高中毕业生,需要先填写自己希望进入的大学的报考编号,我们称之为——填志愿。但是最终每个学生只能被其中一所大学录取。请你帮助计算今年在这个国家,最多能有多少个高中毕业学生进入大学学习。

输入格式:

    第1行包括两个整数,N和M,分别表示今年高中毕业生的数量与今年招生的大学的数量(0≤N,M≤200)。

    输入第2行-输入第N+1行,每行对应一个毕业生今年填写的志愿,每行第一个数字表示学生填写的想去的大学的总数S,后面S个数分别为这些大学的报考编号(每行的数字都由空格分隔,0≤S≤M)。

输出格式:

    第一行输出一个整数,表示在满足学生零个或一个填报志愿进行录取的情况下,国家最多可以安排多少将高中毕业的学生安排进大学进行学习。

样例输入

5 52 2 53 2 3 42 1 53 1 2 51 2

样例输出

4

思路:二分图最大匹配,设置各超级源点超级汇点,然后直接跑网络流就行了。

另外......每个大学居然只收一名学生。真是奇妙的学校......

代码如下:

#include <bits/stdc++.h>#define inf 10007using namespace std;int n,m,E;int G[505][505],layer[505];bool find_layer(){    memset(layer,-1,sizeof(layer));    queue<int>q;    while(!q.empty())q.pop();    q.push(0);    layer[0]=0;    while(!q.empty()){        int now=q.front();        q.pop();        for(int i=1;i<=E;i++){            if(G[now][i] && layer[i]==-1){                layer[i]=layer[now]+1;                q.push(i);                if(i==E)return true;            }        }    }    return false;}int Dinic(){    deque<int>dq;    while(!dq.empty())dq.pop_back();    int vis[505];    memset(vis,0,sizeof(vis));    int ans=0;    while(find_layer()){        memset(vis,0,sizeof(vis));        vis[0]=1;        dq.push_back(0);        while(!dq.empty()){            if(dq.back()==E){                int Min=inf,Min_s;                for(int i=1;i<dq.size();i++){                    int s=dq[i-1],e=dq[i];                    if(G[s][e]<Min){                        Min=G[s][e];                        Min_s=s;                    }                }                ans+=Min;                for(int i=1;i<dq.size();i++){                    int s=dq[i-1],e=dq[i];                    G[s][e]-=Min;                    G[e][s]+=Min;                }                while(!dq.empty() &&dq.back()!=Min_s){                    vis[dq.back()]=0;                    dq.pop_back();                }            }            else{                int flag=1;                for(int i=1;i<=E;i++){                    if(G[dq.back()][i] && !vis[i] && layer[i]==layer[dq.back()]+1){                        flag=0;                        vis[i]=1;                        dq.push_back(i);                        break;                    }                }                if(flag)dq.pop_back();            }        }    }    return ans;}int main(){    while(~scanf("%d%d",&n,&m)){        E=n+m+1;        memset(G,0,sizeof(G));        for(int i=1;i<=n;i++){            int k;            scanf("%d",&k);            for(int j=1;j<=k;j++){                int t;                scanf("%d",&t);                G[i][t+n]=1;            }            G[0][i]=1;        }        for(int i=1;i<=m;i++)G[n+i][E]=1;        cout<<Dinic()<<endl;    }}