虽然这道题是道蓝题,实际上我觉得最多算是绿题。
首先为什么会考虑到二分图匹配呢,因为教室之间不会相互建边,所以很自然的就想到了二分图的定义,但是这道题其实就是求一下当前状态下的最大匹配数,然后判断一下是否是完全匹配。
首先简单的讲一下匈牙利算法,就用上题为例子,我们把教室放在左边,同学放在右边。
这是第一个样例的图。
其实匈牙利算法其实我觉得就是一种贪心的过程,如果当前可以匹配那么就匹配,如果同学已经被匹配了,那么就去找到 哪个同学是和那个教室匹配了,然后看看 那个教室能不能和其他同学匹配........以此类推。那么如果最大匹配数和教师数是一样的那么就说明所有教室都有人了。就输出yes。
上代码:
#pragma clang diagnostic push
#pragma ide diagnostic ignored "cert-err34-c"
#include <bits/stdc++.h>
using namespace std;
struct node {
int f,t,nex;
}rt[1000010];
int head[100000],cnt;
void add(int x,int y) {
cnt ++;
rt[cnt].f =x;
rt[cnt].t = y;
rt[cnt].nex = head[x];
head[x] = cnt;
}
int vis[1000010],fa[100010];
bool fin(int x) {
for(int i = head[x];i;i = rt[i].nex) {
if(!vis[rt[i].t]) {
vis[rt[i].t] = 1;
if(!fa[rt[i].t] || fin(rt[i].t)) {
fa[rt[i].t] = x;
return true;
}
}
}
return false;
}
int main() {
int T;
cin>>T;
int x,y;
while(T --) {
memset(vis,0,sizeof vis);
int ans = 0;
memset(fa,0,sizeof fa);
memset(rt,0,sizeof rt);
memset(head,0,sizeof head);
cnt = 0;
int a,b;
scanf("%d%d",&a,&b);
for(int i = 1;i <= a;i ++) {
scanf("%d",&x);
for(int j = 1;j <= x;j ++) {
scanf("%d",&y);
add(i,y);
}
}
for(int i = 1;i <= a;i ++) {
memset(vis,0,sizeof vis);
if(fin(i))
ans ++;
}
if(ans == a) {
cout<<"YES"<<endl;
}
else {
cout<<"NO"<<endl;
}
}
cout<<endl;
return 0;
}
#pragma clang diagnostic pop