您的位置:首页 > 其它

HDOJ 1083 最大二分匹配 好题

2012-08-30 21:07 344 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1083

我之前不会最大二分匹配,先用的搜索来做(其实这条思路应该也是对的,因为题目给的时间比较宽),超时,而且感觉无法优化了。

后来看了别人的代码,发现原来要用最大二分匹配。

貌似解决最大二分匹配有两种途径:1,网络流;2,匈牙利算法。

我用的是匈牙利算法。

网上有很多关于匈牙利算法的文章,我这里就不再对算法做解释了。

有时候被迫地不求甚解,匈牙利算法的证明我就没有仔细研究,只是能实现罢了。

#include <iostream>
#include <vector>
using namespace std;

const int STUDENT_NUM = 305;
const int COURSE_NUM = 105;
//有多少个学生作为代表
int augmentedPathsNum;
//记录某个课程由哪个学生代表
int mapping[COURSE_NUM];
//处理一个学生的过程中,某个课程是否被访问过
int isVisited[COURSE_NUM];
//记录某个学生参加了哪些课程
vector<int> coursesAttend[STUDENT_NUM];

//用深搜判断从studentId出发,是否存在增广路径
int DFS_isAugmentedPathExist(int studentId)
{
for (int i = 0;i < coursesAttend[studentId].size();i ++)
{
int courseId = coursesAttend[studentId][i];
if (isVisited[courseId] != 0)
continue;
//被访问过
isVisited[courseId] = 1;
if (mapping[courseId] == -1 || DFS_isAugmentedPathExist(mapping[courseId]))
{
mapping[courseId] = studentId;
return 1;
}
}
return 0;
}

int main ()
{
int casesNum;
scanf("%d",&casesNum);
for (int i = 1;i <= casesNum;i ++)
{
int coursesNum, studentsNum;
scanf("%d%d", &coursesNum, &studentsNum);
for (int j = 1;j <= studentsNum;j ++)
coursesAttend[j].clear();
//课程编号为1~coutsesNum
for (int j = 1;j <= coursesNum;j ++)
{
int studentsNumOfCourse;
scanf("%d",&studentsNumOfCourse);
for (int k = 1;k <= studentsNumOfCourse;k ++)
{
int studentId;
scanf("%d",&studentId);
coursesAttend[studentId].push_back(j);
}
}
//mapping[i] = -1表示课程i还没有学生代表
memset(mapping, -1, sizeof(mapping));
augmentedPathsNum = 0;
for (int j = 1;j <= studentsNum;j ++)
{
memset(isVisited, 0, sizeof(isVisited));
if ( DFS_isAugmentedPathExist(j) == 1 )
augmentedPathsNum ++;
}
//每个课程都有学生代表
if (augmentedPathsNum == coursesNum)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: