二分图之最小独立集 HDU 2768
图的独立集:寻找一个点集,其中任意两点在图中无对应边
二分图的最大独立集=图的点数-最大匹配数
1 #include <iostream> 2 #include <cstdio> 3 #include <map> 4 #include <cstring> 5 6 using namespace std; 7 8 struct people 9 { 10 int like,hate; 11 }; 12 13 int head[510]; 14 bool vis[510]; 15 int link[510]; 16 int num; 17 18 struct edge 19 { 20 int fro; 21 int to; 22 int next; 23 }e[250000]; 24 25 void addEdge(int _fro,int _to) 26 { 27 num++; 28 e[num].fro=_fro; 29 e[num].to=_to; 30 e[num].next=head[_fro]; 31 head[_fro]=num; 32 } 33 34 int find(int x) 35 { 36 for(int i=head[x];i!=-1;i=e[i].next) 37 { 38 if(!vis[e[i].to]) 39 { 40 int q=link[e[i].to]; 41 link[e[i].to]=e[i].fro; 42 vis[e[i].to]=true; 43 if(q==-1||find(q)) 44 return 1; 45 link[e[i].to]=q; 46 } 47 } 48 return 0; 49 } 50 51 int main() 52 { 53 int T; 54 scanf("%d",&T); 55 while(T--) 56 { 57 int cnum=0; 58 int dnum=0; 59 int ans=0; 60 num=0; 61 people catpeople[510]; 62 people dogpeople[510]; 63 int c,d,v; 64 scanf("%d%d%d",&c,&d,&v); 65 char a,g; 66 int b,f; 67 memset(head,-1,sizeof(head)); 68 memset(link,-1,sizeof(link)); 69 for(int i=1;i<=v;i++) 70 { 71 cin>>a>>b>>g>>f; 72 if(a=='C') 73 { 74 cnum++; 75 catpeople[cnum].like=b; 76 catpeople[cnum].hate=f; 77 } 78 else if(a=='D') 79 { 80 dnum++; 81 dogpeople[dnum].like=b; 82 dogpeople[dnum].hate=f; 83 } 84 } 85 for(int i=1;i<=cnum;i++) 86 { 87 for(int t=1;t<=dnum;t++) 88 { 89 if(catpeople[i].like==dogpeople[t].hate||catpeople[i].hate==dogpeople[t].like) 90 { 91 addEdge(i,t); 92 } 93 } 94 } 95 for(int i=1;i<=cnum;i++) 96 { 97 memset(vis,false,sizeof(vis)); 98 ans+=find(i); 99 } 100 int reans=v-ans; 101 cout<<reans<<endl; 102 } 103 return 0; 104 }
点的最小覆盖=最大匹配数
用最少的点将边全部覆盖