#include<bits/stdc++.h>
using namespace std;
const int N=300+10;
int p,n,g[N][N],linked[N],v[N];
int dfs(int u){
for(int i=1; i<=n; i++)//逐个学生扫
if(!v[i]&&g[u][i]){//未访问且有边
v[i]=1;//设为已访问
if(linked[i]==-1||dfs(linked[i])){
linked[i]=u;return 1;
}
}
return 0;
}
void hungary(){
int num=0,i;
memset(linked,-1,sizeof(linked));
for(i=1; i<=p; i++){
memset(v,0,sizeof(v));//每次都重置
if(dfs(i)) num++;
}//逐堂课深搜若能满足则NUM+1
if(num==p) printf("YES\n");
else printf("NO\n");
}
int main(){
int t,i,j,x;scanf("%d",&t);
while(t--){
scanf("%d%d",&p,&n);
memset(g,0,sizeof(g));
for(i=1; i<=p; i++){
scanf("%d",&x);
while(x--){
scanf("%d",&j);
g[i][j]=1;
}
}
if(p>n){//课比学生多
printf("NO\n");
continue;
}
hungary();
}
return 0;
}
匈牙利算法
用途:二分图最大匹配
解释:
dfs(int u)中
对编号为u的课逐个学生进行扫描,如果在本课深搜过程中未visit过且课与学生有边时,就设置学生为已visit,然后看在全局状态下是否被link,没有link就设置其link连向本课,并返回1表示成功,如果被link就对其link的课进行深搜
hungary()中
linked是当前状态学生的连接状态,-1是未连,否则值为所连接的课的编号
v是在本节课在深搜时是否visit过的标志,所以每节课开始搜时都要重置
题目:HDU1083
有p门课n个学生,每门课都有若干学生,现在要为每个课程分配一名课代表,每个学生只能担任一门课的课代表,如果每个课都能找到课代表,则输出"YES",否则"NO"。
Input output
2 YES
3 3 NO
3 1 2 3
2 1 2
1 1
3 3
2 1 3
2 1 3
1 1