一个学生可以有多种选择,问能否每个学生刚好选一门课,但是每门课最多只有一个学生可以选择
典型的二分匹配最大匹配,直接套模板
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 17878 | Accepted: 7048 |
Description
Input
Output
Sample Input
2 3 3 3 1 2 3 2 1 2 1 1 3 3 2 1 3 2 1 3 1 1
Sample Output
YES NO
Source
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <limits.h>
#include <ctype.h>
#include <string.h>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <deque>
#include <vector>
#include <set>
#include <map>
#include <memory.h>
using namespace std;
bool g[110][310];//邻接矩阵,true代表有边相连
bool flag,vis[310];//记录v2中的某个点是否被搜索过
int match[310];//记录与v2中的点匹配的点的编号
int p,n;//二分图中左边,右边集合顶点的个数
//匈牙利算法
bool DFS(int u){
int i;
for(i=1;i<=n;++i){
if(g[u][i] && !vis[i])//如果节点i与u相连并且没有被查找过
{
vis[i] = true;
if(match[i]==-1 || DFS(match[i]))//如果i没有在前一个匹配M中,或者i在匹配M中,但是从与i相邻的节点出发可以找到增广路径
{
match[i] = u;//记录查找成功记录,更新匹配M(就是取反)
return true;//返回查找成功
}
}
}
return false;
}
int main(){
int i,j,k,t,v,ans;
scanf("%d",&t);
while(t--){
scanf("%d%d",&p,&n);
for(i=1;i<=p;i++){
for(j=1;j<=n;j++){
g[i][j] = false;
}
}
for(i=1;i<=n;i++){
match[i] = -1;
}
flag = true;
for(i=1;i<=p;i++){
scanf("%d",&k);
if(k == 0){
flag = false;
}
while(k--){
scanf("%d",&v);
g[i][v] = true;
}
}
if(flag==true){
ans = 0;
for(i=1;i<=p;i++){
memset(vis,false,sizeof(vis));//清空上次搜索时的标记
if(DFS(i)==true){
ans++;
}
}
if(ans == p){
printf("YES\n");
}
else{
printf("NO\n");
}
}
else{
printf("NO\n");
}
}
return 0;
}
原文地址:http://blog.csdn.net/zcr_7/article/details/40748191