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 }

浙公网安备 33010602011771号