最简单的匈牙利算法,和上一篇(链接)其实几乎是一样的,都是匈牙利的入门题...
打开本题链接http://poj.org/problem?id=1469
题意:有m个课程和n个学生,现在根据条件就是通过课程找出最多的学生能和课程相匹配,匈牙利算法展露无疑。。。
(其实如果说使用模板的话,就直接在上一篇稍微一改就是了。。。)
#include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> using namespace std; int map[105][305]; bool visited[305]; //标记学生是否被访问 int match[305]; //标记是否已经和课程已经匹配了 //也就是说这两个都是学生具体情况的数组 int n,m; bool find(int i) //查找当前的i是否可以匹配 { int j; for(j=1;j<=n;j++) { if(map[i][j]&&!visited[j])//在这里很有必要说一下visited这个数组,因为在之后的递归中,就会把这个标记好了的对象默认为 //已经和上一次的对象匹配过了,这样就不会再访问这个对象了,这在好几个的连续递归中显得尤为重要 { visited[j]=1; if(match[j]==-1||find(match[j])) //在此次查找的时候其实如果已经匹配过了则会在调用的时候即使是已经匹配成功了,由于 //当时在匹配的时候已经对可以匹配成功的做了match的标记了,就会继续查找他的下一个 //能够匹配的对象 { match[j]=i; return 1; } } } return 0; } int main() { int k,i,x,y,ans; int Case; scanf("%d",&Case); while(Case--) { ans=0; memset(map,0,sizeof(map)); memset(match,-1,sizeof(match)); scanf("%d%d",&m,&n); for(int ww = 1; ww<=m ; ww++) { scanf("%d",&k); for(i=1;i<=k;i++)//对有意思的进行初始化 { scanf("%d",&x); map[ww][x]=1; } } for(i=1;i<=m;i++) { memset(visited,0,sizeof(visited));//开始标记为全部没有访问 if(find(i)) //查找当前的i是否可以匹配成功 ans++; } m==ans ? printf("YES\n") : printf("NO\n"); } return 0; }