Girls and Boys HDU - 1068 二分图匹配(匈牙利)+最大独立集证明
最大独立集证明参考:https://blog.csdn.net/qq_34564984/article/details/52778763
最大独立集证明:
上图,我们用两个红色的点覆盖了所有边。我们证明的前提条件是已经达到最小覆盖。
即条件1.已经覆盖所有边,条件2.所用的点数最小
首先我们来证明蓝色点组成的是一个独立集:如果有两个蓝色点间有边相连,那么这条
边则没有被覆盖,则与条件1矛盾。因此是独立集。
再来证明这个独立集最大: 如果我们要再增加这个独立集中的点,则需要把某个红点变
成蓝点。而由最小覆盖数=最大匹配数的证明我们知道,每一个红点是最大匹配中的一
个匹配点,也就是说每个红点至少连接了一条边。因此当我们将某个红点变成蓝点
时,我们需要牺牲的蓝点的个数是大于等于1的。也就是说,我们最多只能找到数量相等
的其他独立集,而无法找到数量更大的。因此蓝色点集必定为最大独立集。 蓝色点数 =
总点数 - 红色点数,即最大独立集=总数-最小覆盖集。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=500+15; 4 int mp[maxn][maxn],girl[maxn],used[maxn]; 5 void init(){ 6 memset(mp,0,sizeof(mp)); 7 memset(girl,0,sizeof(girl)); 8 } 9 int n; 10 bool find(int x){ 11 for(int i=1;i<=n;i++){ 12 if(mp[x][i]&&used[i]==0){ 13 used[i]=1; 14 if(girl[i]==0||find(girl[i])){ 15 girl[i]=x; 16 return 1; 17 } 18 } 19 } 20 return 0; 21 } 22 int main(){ 23 while(scanf("%d",&n)==1){ 24 int temp; 25 int a; 26 char c; 27 init(); 28 for(int i=1;i<=n;i++){ 29 scanf("%d%c%c%c%d%c",&temp,&c,&c,&c,&temp,&c); 30 //getchar(); 31 for(int j=1;j<=temp;j++){ 32 scanf("%d",&a); 33 mp[i][a+1]=1; 34 } 35 } 36 int sum=0; 37 /*for(int i=1;i<=n;i++){ 38 for(int j=1;j<=n;j++){ 39 cout<<mp[i][j]<<" "; 40 } 41 cout<<endl; 42 }*/ 43 for(int i=1;i<=n;i++){ 44 memset(used,0,sizeof(used)); 45 if(find(i))sum++; 46 } 47 printf("%d\n",n-sum/2); 48 } 49 return 0; 50 }