题目链接:http://poj.org/problem?id=2239
题目大意:
现在有N门课程,从1到N。然后一个学生爱学习,想学习尽可能多门的课程,每门课程在一星期内可以开设多次,但不同课程之间可能有冲突,上课时间为:每周7天,一天12节课,现在给你每门课程的上课时间,求这个学生一周之内最多上几门课程。
解题思路:
可以转换为二分图最大匹配。一个集合为课程,一个集合为上课时间。只需要满足一门课程有且只有一个上课时间就OK了。
关键在于建图,原来想用结构体数组建图,后来发现可能把时间转变为一个数字,就是上课天数和节数转换成 (day-1) * 12 + time就知道是第几天第几节了。
代码如下:
#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;
}