Codechef:Expected Maximum Matching/MATCH(Hall定理)
阿新 • • 發佈:2018-11-01
題解:
利用Hall定理來判斷每個左邊集合是否滿足有完美匹配。
這樣是 的,不過有用狀態很少。
#include <bits/stdc++.h>
using namespace std;
typedef unsigned int uint;
int n,m,lim,y,tot;
double p[6][105];
uint bin[32];
vector <int> val;
vector <uint> nxt[32];
vector <double> f[2];
map <uint,int> id;
inline void dfs(int sta,uint sum) {
if(!sta) {
id[sum]=tot++; int mx=0;
for(int i=1;i<lim;i++) if(sum&bin[i]) mx=max(mx,__builtin_popcount(i));
val.push_back(mx);
for(int i=0;i<lim;i++) {
uint now=sum;
for(int j=0;j<n;j++) if(i&bin[j])
for(int k=1;k<lim;k++) if( (k&bin[j]) && (sum&bin[k^bin[j]])) now|=bin[k];
nxt[i].push_back(now);
} return;
}
if(!(sum&bin[sta])) dfs(sta-1,sum);
if(!(sum&bin[sta])) for(int i=sta;i;i=(i-1)&sta) sum|=bin[i];
dfs(sta-1,sum);
}
inline void trans(int pos,int sta,double v,int o) {
if(pos==n) {
for(int j=0;j<tot;j++)
f[y^1][nxt[sta][j]]+=f[y][j]*v;
return;
}
trans(pos+1,sta,v*(1-p[pos][o]),o);
trans(pos+1,sta|bin[pos],v*p[pos][o],o);
}
int main() {
scanf("%d%d",&n,&m); lim=1<<n;
for(int i=0;i<lim;i++) bin[i]=1ull<<i;
dfs(lim-1,1);
for(int i=0;i<lim;i++)
for(int j=0;j<nxt[i].size();j++) nxt[i][j]=id[nxt[i][j]];
for(int i=0;i<=1;i++) f[i].resize(tot); f[y][id[1]]=1;
for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%lf",&p[i][j]);
for(int i=0;i<m;i++) {
for(int j=0;j<f[y].size();j++) f[y^1][j]=0;
trans(0,0,1,i), y^=1;
}
double ans=0;
for(int i=0;i<tot;i++) ans+=f[y][i]*val[i];
printf("%.6f\n",ans);
}