题目描述
(看完题意,你将要假设什么是公牛,什么是母牛,~~~)
一个星期有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 307
using 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;
}
是时候学一下链式前向星了,哈哈哈。