KM算法 二分图最大权匹配

UVA Live 5985

 

View Code
  1 //Result:1027906     5985     Robbing Gringot...     Wizmann     Accepted     C++     31.649     2012-07-03 10:04:43
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <algorithm>
  6 #include <iostream>
  7 #include <bitset>
  8 #include <vector>
  9 #include <stack>
 10 #include <deque>
 11 #include <cmath>
 12 #include <set>
 13 
 14 using namespace std;
 15 
 16 #define print(x) cout<<x<<endl
 17 #define input(x) cin>>x
 18 #define SIZE 64
 19 #define INF 1<<20
 20 
 21 int pack[SIZE];
 22 int n,m;
 23 int g[SIZE][SIZE];
 24 
 25 bitset<SIZE> visx,visy;
 26 int linky[SIZE];
 27 int lx[SIZE],ly[SIZE];
 28 int slack;
 29 
 30 bool dfs(int x)
 31 {
 32     visx[x]=1;
 33     for(int y=0;y<m;y++)
 34     {
 35         if(visy[y]) continue;
 36         int t=lx[x]+ly[y]-g[x][y];
 37         if(!t)
 38         {
 39             visy[y] = 1;
 40             if(linky[y]==-1 || dfs(linky[y]))
 41             {
 42                 linky[y] = x;
 43                 return 1;
 44             }
 45         }
 46         else if(t<slack)  slack=t;
 47     }
 48     return 0;
 49 }
 50 
 51 int km()
 52 {
 53     memset(linky,-1,sizeof(linky));
 54     memset(lx,0,sizeof(lx));
 55     memset(ly,0,sizeof(ly));
 56     for(int i=0;i<n;i++)
 57     {
 58         for(int j=0;j<m;j++)
 59         {
 60             lx[i]=max(lx[i],g[i][j]);
 61         }
 62     }
 63     for(int i=0;i<n;i++)
 64     {
 65         while(1)
 66         {
 67             visx.reset();
 68             visy.reset();
 69             slack=INF;
 70             if(dfs(i)) break;
 71             for(int j=0;j<n;j++)
 72             {
 73                 if(visx[j]) lx[j]-=slack;
 74             }
 75             for(int j=0;j<m;j++)
 76             {
 77                 if(visy[j]) ly[j]+=slack;
 78             }
 79         }
 80     }
 81     int res=0;
 82     for(int i=0;i<m;i++)
 83     {
 84         if(linky[i]!=-1)
 85         {
 86             res+=lx[linky[i]]+ly[i];
 87         }
 88     }
 89     return res;
 90 }
 91 
 92 int main()
 93 {
 94     freopen("input.txt","r",stdin);
 95     int T,num;
 96     int v[SIZE];
 97     set<int> hash;
 98     input(T);
 99     while(T--)
100     {
101         int maxpack=-INF;
102         scanf("%d%d",&n,&m);
103         memset(g,0,sizeof(g));
104         for(int i=0;i<n;i++)
105         {
106             scanf("%d",pack+i);
107             maxpack=max(maxpack,pack[i]);
108         }
109         for(int i=0;i<m;i++)
110         {
111             scanf("%d",&num);
112             for(int j=0;j<num;j++)
113             {
114                 scanf("%d",v+j);
115             }
116             int half=num>>1;
117             hash.clear();
118             hash.insert(0);
119             for(int j=1;j<(1<<half);j++)
120             {
121                 int sum=0;
122                 for(int k=0;k<half;k++)
123                 {
124                     if(j&(1<<k)) sum+=v[k];
125                 }
126                 if(sum<=maxpack) hash.insert(sum);
127             }
128 
129             for(int j=0;j<(1<<(num-half));j++)
130             {
131                 int sum=0;
132                 for(int k=0;k<(num-half);k++)
133                 {
134                     if(j&(1<<k)) sum+=v[k+half];
135                 }
136                 for(int k=0;k<n;k++)
137                 {
138                     int minus=pack[k]-sum;
139                     if(!g[k][i] && minus<=maxpack && hash.find(minus)!=hash.end())
140                     {
141                         g[k][i]=pack[k];
142                     }
143                 }
144             }
145         }
146 
147         
148         if(n>m)
149         {
150             for(int i=0;i<n;i++)
151             {
152                 for(int j=0;j<i;j++)
153                 {
154                     swap(g[i][j],g[j][i]);
155                 }
156             }
157             swap(m,n);
158         }
159         /*
160         for(int i=0;i<m;i++)
161         {
162             for(int j=0;j<n;j++)
163             {
164                 printf("%d ",g[i][j]);
165             }
166             puts("");
167         }
168         */
169         printf("%d\n",km());
170     }
171     return 0;
172 }

posted on 2012-07-03 18:25  Wizmann  阅读(209)  评论(0)    收藏  举报

导航