题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1068
有n个同学,格式ni:(m) n1 n2 n3表示同学ni有缘与n1,n2,n3成为情侣,求集合中不存在有缘成为情侣的同学的最大同学数。
独立集(图的顶点集的子集,其中任意两点不相邻)
二分图中 最大独立集 = 顶点个数 - 最大匹配数
因为男女不知道,将一个人拆成两个性别,求最大匹配后,除以2就行了。
这种做法比较难理解。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 const int N = 1e3 + 5; 6 struct Edge { 7 int next , to; 8 }edge[N * N]; 9 int head[N] , cnt; 10 int match[N]; 11 bool vis[N]; 12 13 void init() { 14 memset(head , -1 , sizeof(head)); 15 memset(match , -1 , sizeof(match)); 16 memset(vis , false , sizeof(vis)); 17 cnt = 0; 18 } 19 20 inline void add(int u , int v) { 21 edge[cnt].next = head[u]; 22 edge[cnt].to = v; 23 head[u] = cnt++; 24 } 25 26 bool dfs(int u) { 27 for(int i = head[u] ; ~i ; i = edge[i].next) { 28 int v = edge[i].to; 29 if(!vis[v]) { 30 vis[v] = true; 31 if(match[v] == -1 || dfs(match[v])) { 32 match[v] = u; 33 return true; 34 } 35 } 36 } 37 return false; 38 } 39 40 int hungry(int n) { 41 int res = 0; 42 for(int i = 0 ; i < n ; ++i) { 43 memset(vis , false , sizeof(vis)); 44 if(dfs(i)) 45 res++; 46 } 47 return res; 48 } 49 50 int main() 51 { 52 int n; 53 while(~scanf("%d" , &n)) { 54 init(); 55 int v; 56 for(int i = 0 ; i < n ; ++i) { 57 int num1 , num; 58 scanf("%d: (%d) ", &num1 , &num); 59 while(num--) { 60 scanf("%d" , &v); 61 add(i , v); 62 } 63 } 64 printf("%d\n" , n - hungry(n)/2); 65 } 66 return 0; 67 }