题意
找出一个最大的集合使得该集合的任意两个人没有关系
题解
最大匹配:二分图中边集的数目最大的那个匹配;
最大独立集:在N个点的图G中选出m个点,使这m个点两两之间没有边的点中,m的最大值。
在二分图中, 最大独立集 = 顶点数-最大匹配数 |
题目没有明确说明些是男的哪些是女的,说明没有明显的二分图,所以将一个人拆成两个人进行最大匹配, 所以多了一倍, 最大匹配数应该是求出来的数除以2
代码
#include <bits/stdc++.h>
using namespace std;
#define rg register
#define sc scanf
#define pf printf
typedef long long ll;
class Hungary {
public:
static const int MAXN = 1e5+100;
static const int MAXM = 2e5+10;
struct EDGE {
int v, to;
}e[MAXM];
int head[MAXM], cnt = 0;
inline void add ( int u, int v ) {
e[cnt].v = v, e[cnt].to = head[u]; head[u] = cnt++;
}
int n, ans;
int link[MAXN];
bool use[MAXN];
Hungary ( ) { };
Hungary ( int _n ) : n(_n) { };
void ini ( int n ) {
this->n = n;
cnt = 0; memset( head, -1, sizeof(head) );
}
private:
bool dfs ( int u ) {
for ( int k = head[u]; k != -1; k = e[k].to ) {
int v = e[k].v;
if ( use[v] ) continue;
use[v] = true;
if ( link[v] == -1 || dfs ( link[v] ) ) {
link[v] = u;
return true;
}
}
return false;
}
public:
int run ( ) {
ans = 0;
memset ( link, 255, sizeof ( link ) );
for ( int i = 0; i < n; ++i ) {
memset ( use, 0, sizeof ( use ) );
if ( dfs ( i ) )
++ans;
}
return ans;
}
}h;
int main ( ) {
int n,
u, num, v; // char ch;
while ( ~ sc ( "%d", &n ) ) {
h.ini( n );
for ( int i = 0; i < n; ++i ) {
// scanf ( "%d%c%c%c%d%c)", &u, &ch, &ch, &ch, &num, &ch );
scanf ( "%d: (%d)", &u, &num );
for ( int j = 0; j < num; j++ ) {
scanf ( "%d", &v );
h.add( u, v );
}
}
pf ( "%d\n", n-h.run()/2 );
}
return 0;
}