二分图之最小独立集 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 }
View Code

点的最小覆盖=最大匹配数

用最少的点将边全部覆盖

posted @ 2015-08-28 10:53  相儒以沫  阅读(205)  评论(0编辑  收藏  举报