caioj 1123 上课(二分图匹配)

来源:互联网 发布:大乐网络代理什么游戏 编辑:程序博客网 时间:2024/06/04 19:36

题目描述
(看完题意,你将要假设什么是公牛,什么是母牛,~~~)
一个星期有7天,每天有12节课。
有n门课程,但是有些课程上课的时间是冲突的,
求最多能上多少门课程。
Input
第一行为整数 n (1 <= n <= 300), 表示课程的总数。下来n行表示n门课程的信息。每行第一个数为整数 t (1 <= t <= 7*12), 表示学生可以学习该门课程的时间段总数。下来t对整数,每对整数为 p (1 <= p <= 7) and q (1 <= q <= 12), 表示该门课程在每个星期的第p天的第q节课上课。
Output
输出一行,最多能上多少门课。

Sample Input
5
1 1 1
2 1 1 2 2
1 2 2
2 3 2 3 3
1 3 3

Sample Output
4

这是一道二分图匹配的题,但是要转化模型,思考一下就可以看出要匹配的应该是课程n与上课时间。然后就是一道模板题了。但是在写代码的时候就会发现一个问题就是课程n与上课的时间如何进行匹配储存。我这里是用一个二维的数组分别存课程与时间的。然后在dfs函数里面加个参数,1为课程,2为时间,在搜索时候比较容易转化。这是我的代码:
    #include<cstdio>#include<vector>#include<cstring>#define maxn 307using namespace std;vector<int> lesson[maxn][3];int match[maxn][3];int n;bool check[maxn][3];int ans;bool dfs(int z,int y){     int c=lesson[z][y].size();     int p;     if(y==1)p=2;     if(y==2)p=1;     for(int i=0;i<c;i++)     {         int v=lesson[z][y][i];         if(!check[v][y])         {             if(match[v][y]==0||dfs(match[v]))             {                 match[v][y]=z;                 match[z][y]=v;                 return true;             }         }     }     return false;}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        int h;scanf("%d",&h);        for(int j=1;j<=h;j++)        {            int x,y;            scanf("%d%d",&x,&y);            lesson[i][1].push_back(x*12+y);            lesson[x*12+y][2].push_back(n);        }    }    for(int i=1;i<=n;i++)    (        if(!match[n][1])        {        memset(check,0,sizeof(check));        if(dfs(n,1))ans++;        }    )    printf("%d\n",ans);    return 0;}
我用邻接表做比较麻烦,用链式前向星就比较简单了,别人的代码:
    #include<iostream>  #include<cstdio>  #include<cstring>  #include<vector>  #include<algorithm>  using namespace std;  #define N 310  int soursenum;  int map[N][90];  int match[N];  bool use[N];  bool find(int u) //查询匹配的课程  {      for(int i = 1; i <= 84; ++i)      {          if(!use[i] && map[u][i])          {              use[i] = true;              if(match[i] == -1 || find(match[i]))              {                  match[i] = u;                  return true;              }          }      }      return false;  }  int sum()  {      int sumall = 0;      for(int i = 1; i <= soursenum; ++i)      {          memset(use, false, sizeof(use));          if(find(i))              sumall++;      }      return sumall;  }  int main()  {      int everynum;      int day, time;      while(scanf("%d", &soursenum) != EOF)      {          memset(map, 0, sizeof(map));          memset(match, -1, sizeof(match));          for(int k = 1; k <= soursenum; ++k)          {              scanf("%d", &everynum);              for(int i = 1; i <= everynum; ++i)              {                  scanf("%d%d", &day, &time);                  map[k][(day - 1) * 12 + time] = 1; //巧妙转换              }          }          printf("%d\n", sum());      }      return 0;  }    

是时候学一下链式前向星了,哈哈哈。

原创粉丝点击