KM算法 二分图最大权匹配
2012-07-03 18:25
316 查看
UVA Live 5985
View Code
View Code
//Result:1027906 5985 Robbing Gringot... Wizmann Accepted C++ 31.649 2012-07-03 10:04:43 #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <iostream> #include <bitset> #include <vector> #include <stack> #include <deque> #include <cmath> #include <set> using namespace std; #define print(x) cout<<x<<endl #define input(x) cin>>x #define SIZE 64 #define INF 1<<20 int pack[SIZE]; int n,m; int g[SIZE][SIZE]; bitset<SIZE> visx,visy; int linky[SIZE]; int lx[SIZE],ly[SIZE]; int slack; bool dfs(int x) { visx[x]=1; for(int y=0;y<m;y++) { if(visy[y]) continue; int t=lx[x]+ly[y]-g[x][y]; if(!t) { visy[y] = 1; if(linky[y]==-1 || dfs(linky[y])) { linky[y] = x; return 1; } } else if(t<slack) slack=t; } return 0; } int km() { memset(linky,-1,sizeof(linky)); memset(lx,0,sizeof(lx)); memset(ly,0,sizeof(ly)); for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { lx[i]=max(lx[i],g[i][j]); } } for(int i=0;i<n;i++) { while(1) { visx.reset(); visy.reset(); slack=INF; if(dfs(i)) break; for(int j=0;j<n;j++) { if(visx[j]) lx[j]-=slack; } for(int j=0;j<m;j++) { if(visy[j]) ly[j]+=slack; } } } int res=0; for(int i=0;i<m;i++) { if(linky[i]!=-1) { res+=lx[linky[i]]+ly[i]; } } return res; } int main() { freopen("input.txt","r",stdin); int T,num; int v[SIZE]; set<int> hash; input(T); while(T--) { int maxpack=-INF; scanf("%d%d",&n,&m); memset(g,0,sizeof(g)); for(int i=0;i<n;i++) { scanf("%d",pack+i); maxpack=max(maxpack,pack[i]); } for(int i=0;i<m;i++) { scanf("%d",&num); for(int j=0;j<num;j++) { scanf("%d",v+j); } int half=num>>1; hash.clear(); hash.insert(0); for(int j=1;j<(1<<half);j++) { int sum=0; for(int k=0;k<half;k++) { if(j&(1<<k)) sum+=v[k]; } if(sum<=maxpack) hash.insert(sum); } for(int j=0;j<(1<<(num-half));j++) { int sum=0; for(int k=0;k<(num-half);k++) { if(j&(1<<k)) sum+=v[k+half]; } for(int k=0;k<n;k++) { int minus=pack[k]-sum; if(!g[k][i] && minus<=maxpack && hash.find(minus)!=hash.end()) { g[k][i]=pack[k]; } } } } if(n>m) { for(int i=0;i<n;i++) { for(int j=0;j<i;j++) { swap(g[i][j],g[j][i]); } } swap(m,n); } /* for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { printf("%d ",g[i][j]); } puts(""); } */ printf("%d\n",km()); } return 0; }
相关文章推荐
- BZOJ 4819: [Sdoi2017]新生舞会 01分数规划 二分图最大权匹配(KM算法)/费用流
- HDU 2255 KM算法 二分图最大权值匹配
- 二分图最大权匹配(KM算法)
- POJ2195 Going Home——二分图最大带权匹配的KM算法——pku2195
- [HDOJ3718]Similarity(KM算法,二分图最大匹配)
- KM算法详解+模板(二分图最大权值匹配)
- 二分图-最大匹配,最小路径覆盖,最小点覆盖(KM算法)
- uoj #80. 二分图最大权匹配 KM算法
- KM算法 求二分图最大权值的完美匹配 【模板 记录】
- CSU 1623 Inspectors(二分图最大权匹配 KM算法)(UVAlive 6879)
- My Brute (hdu 3315 二分图最大权匹配KM算法)
- 二分图 最大权匹配 km算法
- 初涉二分图的最大权匹配 KM算法
- KM算法模板(二分图的最大权匹配)
- hdu 2255 二分图最大权匹配 KM算法kuangbin模板
- 【二分图最大权匹配---KM算法】
- 理论: 图论(11): 二分图的最大权匹配(KM算法)HDU 2255
- hdu2255 奔小康赚大钱 【二分图最大权匹配-KM算法】
- hdu 2255 二分图最大权匹配 km算法模板
- 二分图最大权值匹配KM算法