[二分图最大匹配]LuoGu P2417 课程
题目地址LuoGu P2417 课程
题目描述
n个学生去p个课堂,每一个学生都有自己的课堂,并且每个学生只能去一个课堂,题目要求能够安排每一个课堂都有人吗?
输入输出格式
输入格式:
第一行是测试数据的个数,
每组测试数据的开始分别是p和n,
接着p行,每行的开始是这个课堂的学生人数m,接着m个数代表该课堂的学生编号
输出格式:
如果该组数据能够这样安排就输出YES,否则输出NO。
输入输出样例
输入样例#1:
2
3 3
3 1 2 3
2 1 2
1 1
3 3
2 1 3
2 1 3
1 1
输出样例#1:
YES
NO
说明
对于100%的数据, $$n\(\le 100,m\le 20000\)$
二分图最大匹配..裸的 没有什么难度 跑一遍就过了 唯一需要考虑的就是 如果n>m的话 我们就直接输出NO
扔代码..
//#define fre yes
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 20010 * 2;
int curch[maxn];
int head[maxn];
int ver[maxn];
int to[maxn];
bool Vis[maxn];
int n,m,k,tot,ans;
template<typename T>inline void read(T&x)
{
x = 0;char c;int lenp = 1;
do { c = getchar();if(c == '-') lenp = -1; } while(!isdigit(c));
do { x = x * 10 + c - '0';c = getchar(); } while(isdigit(c));
x *= lenp;
}
void addedge(int x,int y)
{
ver[tot] = y;
to[tot] = head[x];
head[x] = tot++;
}
bool can(int x)
{
for (int i=head[x];~i;i=to[i])
{
int y = ver[i];
if(!Vis[y])
{
Vis[y] = 1;
if(!curch[y]||can(curch[y]))
{
curch[y] = x;
return 1;
}
} } return 0;
}
int main()
{
read(k);
while(k--)
{
// for (int i=0;i<maxn;i++) { curch[i] = 0;head[i] = -1;ver[i] = 0;to[i] = 0; }
memset(curch,0,sizeof(curch));
memset(head,-1,sizeof(head));
memset(ver,0,sizeof(ver));
memset(to,0,sizeof(to));
ans = 0;tot = 0;
read(n);read(m);
for (int i=1;i<=n;i++)
{
int x;
read(x);
for (int j=1;j<=x;j++)
{
int y;
read(y);
addedge(i,y);
}
}
if(n > m)
{
puts("NO");
continue;
}
for (int i=1;i<=n;i++)
{
memset(Vis,false,sizeof(Vis));
if(can(i)) ans++;
} if(ans == n) puts("YES");
else puts("NO");
} return 0;
}