dfs
#include<iostream>
#include<queue>
using namespace std;
//X
const int N = 205;
//Y
const int M = 205;
//line[i][j]代表i到j有边,只存i->j的,没有存j到i的
bool line[N][M];
//是否访问过
bool visit[M];
//y连接的x(从右到左)
int my[M];
int n, m;
bool Find(int x) {
for (int i = 1; i <= n; ++i) {
//有边,且没被访问过
if (line[x][i] && !visit[i]) {
visit[i] = true;
//如果是没有被连接,或者可以调整出位置
if (my[i] == 0 || Find(my[i])) {
my[i] = x;
return true;
}
}
}
return false;
}
int Hungarian() {
int cnt = 0;
memset(my, 0, sizeof(my));
for (int i = 1; i <= n; ++i) {
memset(visit, false, sizeof(visit));
if (Find(i)) {
++cnt;
}
}
return cnt;
}
int main() {
while (~scanf("%d%d", &n, &m)) {
memset(line, false, sizeof(line));
for (int i = 1; i <= n; ++i) {
int s;
scanf("%d", &s);
while (s--) {
int t;
scanf("%d", &t);
line[i][t] = true;
}
}
printf("%d\n", Hungarian());
}
return 0;
}
bfs
有一个不同的就是visit不再是每次memset成0而是在处理第i个点的时候,visit[y]=i代表被使用过了
#include<iostream>
#include<queue>
using namespace std;
//X
const int N = 205;
//Y
const int M = 205;
//line[i][j]代表i到j有边,只存i->j的,没有存j到i的
bool line[N][M];
//x连接的y(从左到右)
int mx[N];
//y连接的x(从右到左)
int my[M];
//是否访问过
int visit[M];
//前驱,用来回溯的
int pre[N];
int n, m;
int Hungarian() {
memset(mx, 0, sizeof(mx));
memset(my, 0, sizeof(my));
memset(visit, 0, sizeof(visit));
int cnt = 0;
for (int i = 1; i <= n; ++i) {
//没有连接的y
if (mx[i] == 0) {
queue<int> q;
q.push(i);
pre[i] = -1;
bool flag = false;
while (!q.empty() && !flag) {
int u = q.front();
q.pop();
//遍历u连接的边
for (int v = 1; v <= m; ++v) {
//有边,且y没被访问过
if (line[u][v] && visit[v] != i) {
visit[v] = i;
//如果y被别人连了,就要调整对应的x
if (my[v] > 0) {
q.push(my[v]);
pre[my[v]] = u;
}
else {
//连接完了
flag = true;
//调整连接
while (u != -1) {
int temp = mx[u];
mx[u] = v;
my[v] = u;
u = pre[u];
v = temp;
}
break;
}
}
}
}
if (mx[i] > 0) {
++cnt;
}
}
}
return cnt;
}
int main() {
while (~scanf("%d%d", &n, &m)) {
memset(line, false, sizeof(line));
for (int i = 1; i <= n; ++i) {
int s;
scanf("%d", &s);
while (s--) {
int t;
scanf("%d", &t);
line[i][t] = true;
}
}
printf("%d\n", Hungarian());
}
return 0;
}