二维的情况:把所有x和y转成二分图,跑最大匹配即可
推广到三维:因为
a
∗
b
∗
c
≤
5000
a*b*c\leq5000
a∗b∗c≤5000,所以有一维必定小于17,则
2
17
2^{17}
217枚举这一维的状态,剩下的二维直接做就好了
注意memset会T
Code:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int cur=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {cur=(cur<<1)+(cur<<3)+(ch^48);ch=getchar();}
return cur*f;
}
const int N=1e5+5,INF=1e9;
int vis[N<<1],head[N],nxt[N<<1],c[N<<1],tot=1;
int curr[N<<1];
inline void add(int x,int y,int z){
vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;c[tot]=z;
vis[++tot]=x;nxt[tot]=head[y];head[y]=tot;c[tot]=0;
}
int st[N];
int s,t;
inline bool bfs(){
for(int i=s;i<=t;i++) st[i]=-1;
queue<int>q;
st[s]=1;q.push(s);
while(!q.empty()){
int x=q.front();q.pop();
for(int i=head[x];i;i=nxt[i])
if(c[i] && st[vis[i]]==-1){
st[vis[i]]=st[x]+1;
q.push(vis[i]);
if(vis[i]==t) return 1;
}
}
return 0;
}
int dfs(int v,int flow){
if(v==t) return flow;
int rest=flow,k;
for(int &i=curr[v];i && rest;i=nxt[i])
if(c[i] && st[vis[i]]==st[v]+1){
int k=dfs(vis[i],min(rest,c[i]));
if(!k) st[vis[i]]=-1;
c[i]-=k;c[i^1]+=k;rest-=k;
if(!flow) break;
}
return flow-rest;
}
int pt[N],yy[N],zz[N];
int cnt,n,m,x,y,z,aa,bb,cc;
int cur,mn,mnx,mx;
struct point{int x,y,z;}b[5010];
inline int dinic(int mxflow){
int flow=0;
while(bfs()){
for(int i=0;i<=t;i++) curr[i]=head[i];
while(flow=dfs(s,INF)){
mxflow+=flow;
if(mxflow>=mn) return mxflow;
}
}
return mxflow;
}
inline void solve(int x){
cnt=s=mx=0;
int ans=0;
for(int i=0;i<aa;i++){
if(x&(1<<i)) ans++,pt[i+1]=0;
else pt[i+1]=1;
}
for(int i=1;i<=cur;i++) if(pt[b[i].x]) yy[++cnt]=b[i].y,zz[cnt]=b[i].z;
for(int i=1;i<=cnt;i++) mx=max(mx,max(yy[i],zz[i]));
t=mx*2+1;
tot=1;for(int i=s;i<=t;i++) head[i]=0;
for(int i=1;i<=mx;i++) add(s,i,1),add(i+mx,t,1);
for(int i=1;i<=cnt;i++) add(yy[i],zz[i]+mx,1);
mn=min(mn,dinic(ans));
}
int bin[50];
int main(){
int T=read();bin[0]=1;
for(int i=1;i<=20;i++) bin[i]=bin[i-1]<<1;
while(T--){
aa=read(),bb=read(),cc=read(),mnx=min(aa,min(bb,cc)),cur=0,mn=INF;
if(bb==mnx) swap(aa,bb);
else if(cc==mnx) swap(aa,cc);
for(int i=1;i<=aa;i++)
for(int j=1;j<=bb;j++)
for(int k=1;k<=cc;k++){
x=read();
if(x) b[++cur].x=i,b[cur].y=j,b[cur].z=k;
}
for(int i=0;i<bin[aa];i++) solve(i);
cout<<mn<<"\n";
}
}