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 }

猜你喜欢

转载自www.cnblogs.com/ttttttttrx/p/10256785.html
今日推荐