大意就是有n个人,每个人与其他的某几个人有关系,这个关系且称为浪漫关系,然后最后求一个最大的集合,使得集合中所有的人两两之间都不存在浪漫关系。
看到之后就可以发现,这是一道非常明显的最大独立集的问题,可以转化为二分图来做,还是最经典的拆点建图,然后根据定理,最大独立集=顶点数-最小点覆盖数。 而对于这道题来说,我们可以发现这个浪漫关系是相互的。
而我们的建图中,按理来说应该是一边是男的点,一边是女的点这样连边,但是题目中没说性别的问题。
只能将每个点拆成两个点,一个当作是男的点,一个当作是女的点了,然后连边。由于关系是相互的,这样就造成了边的重复。也就是边集是刚才的二倍,从而导致了最大匹配变成了二倍。
那么 ,最大独立集=顶点数-最大匹配/2,所以最终答案就呼之欲出了。
/*
ID: sdj22251
PROG: subset
LANG: C++
*/
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define MAXN 555
#define MAXM 104444
#define INF 100000000
#define PI acos(-1.0)
#define eps 1e-12
#define L(X) X<<1
#define R(X) X<<1|1
using namespace std;
struct node
{int v, next;
}edge[MAXN * MAXN];
int e, head[MAXN], mark[MAXN], cx[MAXN], cy[MAXN], n;
void insert(int x, int y)
{edge[e].v = y;edge[e].next = head[x];head[x] = e++;
}
int path(int u)
{for(int i = head[u]; i != -1; i = edge[i].next){int v = edge[i].v;if(!mark[v]){mark[v] = 1;if(cy[v] == -1 || path(cy[v])){cx[u] = v;cy[v] = u;return 1;}}}return 0;
}
int solve()
{int ans = 0;memset(cx, -1, sizeof(cx));memset(cy, -1, sizeof(cy));for(int i = 1; i <= n; i++){memset(mark, 0, sizeof(mark));ans += path(i);}return ans;
}
int main()
{int x, y, m;while(scanf("%d", &n) != EOF){e = 0;memset(head, -1, sizeof(head));for(int i = 0; i < n; i++){scanf("%d: (%d)", &x, &m);while(m--){scanf("%d", &y);insert(x + 1, y + 1);}}int ans = n - solve() / 2;printf("%d\n", ans);}return 0;
}