LOJ 1373 最大团

题意: 给出了n个阳离子和m个阴离子,给出了他们之间的吸引关系。 现在想要求出一个集合,这个集合中至少有一个阳离子, 也至少有一个阴离子。 要求每个阳离子吸引所有的阴离子。求出这个集合中元素的最大数目是多少?

 

思路: 这道题开始想的时候没有思路,后来知道是一个最大团, 最大团等于节点数减去最大匹配。

但是普通的最大团左右集合可以为空。 但是这里要求必须至少有一个元素, 这里我们可以枚举至少的那个点对,然后再求最大团。

AC代码:

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <string>
  4 #include <iostream>
  5 #include <queue>
  6 #include <vector>
  7 using namespace std;
  8 const int N = 505;
  9 
 10 struct EDGE
 11 {
 12     int u, v, next;
 13 } edge[N*N];
 14 
 15 int num, head[N], cx[N], cy[N], n, m;
 16 bool used[N];
 17 char map[N][N];
 18 
 19 void init()
 20 {
 21     scanf("%d%d", &n, &m);
 22     for(int i=1; i<=n; i++)
 23         scanf("%s", map[i]+1);
 24 }
 25 
 26 void add(int u, int v)
 27 {
 28     edge[num].u = u;
 29     edge[num].v = v;
 30     edge[num].next = head[u];
 31     head[u] = num++;
 32 }
 33 
 34 bool can(int u)
 35 {
 36     int v;
 37     for(int i=head[u]; i!=-1; i=edge[i].next)
 38     {
 39         v = edge[i].v;
 40         if(used[v]) continue;
 41         used[v] = 1;
 42         if(cy[v] == -1 || can(cy[v]) )
 43         {
 44             cx[u] = v;
 45             cy[v] = u;
 46             return true;
 47         }
 48     }
 49     return false;
 50 }
 51 
 52 int xiyali(int total)
 53 {
 54     int ans = 0;
 55     memset(cx, -1, sizeof(cx));
 56     memset(cy, -1, sizeof(cy));
 57     for(int i=1; i<=n; i++)
 58     {
 59         memset(used, 0, sizeof(used));
 60         if(cx[i] == -1 && can(i))
 61             ans++;
 62     }
 63     return total-ans;
 64 }
 65 
 66 void solve()
 67 {
 68     int ans = 0, u, v;
 69     vector<int> g1, g2;
 70     for(int i=1; i<=n; i++)
 71     {
 72 
 73         for(int j=1; j<=m; j++)
 74         {
 75 
 76             if(map[i][j] == '1')
 77             {
 78                 g1.clear();
 79                 g2.clear();
 80                 for(int k=1; k<=n; k++)
 81                 {
 82                     if(map[k][j] == '1' && k!=i)
 83                         g1.push_back(k);
 84                 }
 85                 for(int k=1; k<=m; k++)
 86                 {
 87                     if(map[i][k] == '1' && k!=j)
 88                         g2.push_back(k);
 89                 }
 90                 num = 0;
 91                 memset(head, -1, sizeof(head));
 92                 for(int k1=0; k1 <g1.size(); k1++)
 93                 {
 94                     u = g1[k1];
 95                     for(int k2=0; k2<g2.size(); k2++)
 96                     {
 97                         v = g2[k2];
 98                         if(map[u][v] == '0')
 99                             add(u, v);
100                     }
101                 }
102                 ans = max(ans, 2+xiyali(g1.size()+g2.size()));
103 
104             }
105         }
106     }
107     printf("%d\n", ans);
108 }
109 
110 int main()
111 {
112     int t;
113     scanf("%d", &t);
114     for(int i=1; i<=t; i++)
115     {
116         init();
117         printf("Case %d: ",i);
118         solve();
119     }
120     return 0;
121 }

 

 

posted @ 2012-10-11 21:07  Gu Feiyang  阅读(206)  评论(0)    收藏  举报