题意
n个英雄,m个怪兽,某个英雄可以杀死某些编号的怪兽,但他只能杀死这些怪兽中的一只;有k瓶药水,某个英雄喝了可以多杀一只怪兽,但是最多喝一瓶;给出第i个英雄可以杀的怪兽编号,问总共最多杀几只怪兽。
思路
连续做两次二分图匹配。做第一次匹配后不需要处理已经匹配过的边,因为有多种匹配方式,每种匹配方式对第二次匹配得到的结果可能不一样,做一次二分图匹配只能得到最大匹配数。连着做二分图匹配可以保证第一次加第二次最优。
#include<set>
#include<map>
#include<stack>
#include<cstdio>
#include<queue>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 0x3f3f3f3f
#define pi acos(-1.0)
using namespace std;
const int maxn = 1e3+5;
int n, m, k;
int g[maxn][maxn], p[maxn];
bool vis[maxn];
bool dfs(int u){
for(int i = 1; i <= m; i++){
if(g[u][i] && !vis[i]){
vis[i] = 1;
if(p[i] == 0 || dfs(p[i])){
p[i] = u;
return 1;
}
}
}
return 0;
}
int main(){
scanf("%d %d %d", &n, &m, &k);
int u, v;
for(int i = 1; i <= n; i++){
scanf("%d", &u);
for(int j = 1; j <= u; j++){
scanf("%d", &v);
g[i][v] = 1;
}
}
int ans = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++) vis[j] = 0;
if(dfs(i)) ans++;
}
int cnt = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++) vis[j] = 0;
if(dfs(i)) cnt++;
}
ans += min(cnt, k);
printf("%d\n", ans);
return 0;
}