题意大概是,有n个英雄,m个怪兽,k瓶药。每一个英雄都有自己能够打败的一个怪兽列表。每个人只能打一只怪兽,但是每个人还有一次嗑药的机会,嗑一次药就能再打败一个怪兽。问最多能打败多少只怪兽。
建图如上:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#define INF 0x3f3f3f3f
#define len 100010
using namespace std;
struct edge{
int u, v, f, nxt;
};
edge e[len];
int head[len], hcnt;
int dep[len], cur[len];
int S, T;
void Init(){
memset(head, -1, sizeof (head));
memset(cur, 0, sizeof (cur));
hcnt = 0;
}
void adde(int u, int v, int f){
e[hcnt].u = u; e[hcnt].v = v; e[hcnt].f = f;
e[hcnt].nxt = head[u]; head[u] = hcnt ++;
e[hcnt].u = v; e[hcnt].v = u; e[hcnt].f = 0;
e[hcnt].nxt = head[v]; head[v] = hcnt ++;
}
bool bfs(){
queue <int> q;
memset(dep, -1, sizeof (dep));
dep[S] = 0; q.push(S);
while (!q.empty()){
int h = q.front(); q.pop();
for (int i=head[h]; ~i; i=e[i].nxt){
int v = e[i].v;
if (dep[v] == -1 && e[i].f > 0){
dep[v] = dep[h] + 1;
q.push(v);
if (v == T) return true;
}
}
}
return false;
}
int dfs(int x, int mw){
if (x == T || !mw) return mw;
int sum = 0;
for (int i=cur[x]; ~i; i = e[i].nxt){
cur[x] = i;
int v = e[i].v;
if (dep[v] == dep[x] + 1 && e[i].f > 0){
int flow = dfs(v, min(e[i].f, mw));
if (flow){
sum += flow;
mw -= flow;
e[i].f -= flow;
e[i^1].f += flow;
if (!mw) break;
}
}
}
if (!sum) dep[x] = -1;
return sum;
}
int dinic(){
int ans = 0;
while(bfs()){
for (int i=S; i<=T; i++) cur[i] = head[i];
ans += dfs(S, INF);
}
return ans;
}
int main(){
int n, m, k;
Init();
scanf("%d%d%d", &n, &m, &k);
S = 0; T = n + m + 2;
for (int i=1; i<=n; i++) {
adde(S, i, 1);
adde(T-1, i, 1);
}
for (int i=1; i<=n; i++){
int num; scanf("%d", &num);
for (int j=1; j<=num; j++){
int p; scanf("%d", &p);
adde(i, p+n, 1);
}
}
for (int i=1; i<=m; i++) adde(i+n, T, 1);
adde(S, T-1, k);
int ans = dinic();
printf("%d\n", ans);
return 0;
}