1. 程式人生 > >Girls and Boys HDU - 1068 二分圖匹配(匈牙利)+最大獨立集證明

Girls and Boys HDU - 1068 二分圖匹配(匈牙利)+最大獨立集證明

fin include while ++ .net 覆蓋數 article c++ 無法

最大獨立集證明參考: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 }

Girls and Boys HDU - 1068 二分圖匹配(匈牙利)+最大獨立集證明