洛谷 P3231 [HNOI2013]消毒 / YbtOJ「图论」第1章 二分图匹配 L. 消毒问题 题解--zhengjun

思路

先考虑二维的怎么做,发现选了一列要填,那么肯定是这一列都填一遍,然后发现如果有一个点要被填,也就是这一列和这一行只要要填一个,建出二分图,直接跑个最小点覆盖(也就是选出最少的点使得每条边都至少有一个点被覆盖,数值上等于最大匹配)。

然后转化到三维上去,就是直接枚举一维的覆盖情况,然后转化到二维上跑一边最大匹配就行了。

复杂度:\(O(2^{\min\{a,b,c\}}\times\frac{a\times b\times c}{\min\{a,b,c\}}\times\sqrt{a+b+c-\min\{a,b,c\}})\)

实测能通过。

代码

#include<bits/stdc++.h>
#define pb push_back
using namespace std;const int N=5e3+10,M=N*4;struct edges{int to,c,nex;}edge[M];
int T,a,b,c,s,t,ans,cnt[1<<18],head[N],kk,id[3][N],n,p[N][N][2],tot[N],d[N],cur[N];
void add(int u,int v,int c){edge[++kk]={v,c,head[u]};head[u]=kk;edge[++kk]={u,0,head[v]};head[v]=kk;}
bool bfs(){
	queue<int>q;q.push(s);for(int i=0;i<=t;i++)d[i]=-1;d[s]=0;cur[s]=head[s];for(int u;!q.empty();q.pop()){
		u=q.front();for(int i=head[u],v;v=edge[i].to,i;i=edge[i].nex)
			if(!~d[v]&&edge[i].c)d[v]=d[u]+1,cur[v]=head[v],q.push(v);
	}return ~d[t];
}
int dfs(int u,int lim=1e9){
	if(u==t)return lim;int flow=0;for(int i=cur[u],v;v=edge[i].to,i&&flow<lim;i=edge[i].nex){
		cur[u]=i;if(d[v]!=d[u]+1||!edge[i].c)continue;int f=dfs(v,min(lim-flow,edge[i].c));
		if(!f)d[v]=-1;edge[i].c-=f;edge[i^1].c+=f;flow+=f;
	}return flow;
}
int dinic(){int maxflow=0;while(bfs())maxflow+=dfs(s);return maxflow;}
void clear(){for(int i=0;i<=t;i++)head[i]=0;}
void solve(int now){
	kk=1;for(int i=0;i<a;i++)if(!(now>>i&1))for(int j=0;j<tot[i];j++)add(p[i][j][0],p[i][j][1]+b,1);
	for(int i=0;i<b;i++)add(s,i,1);for(int i=0;i<c;i++)add(i+b,t,1);ans=min(ans,dinic()+cnt[now]);clear();
}
void get(){
	for(int i=0,x;i<a;i++)for(int j=0;j<b;j++)for(int k=0;k<c;k++)cin>>x,x&&(id[0][n]=i,id[1][n]=j,id[2][n++]=k);
	if(b<a&&b<=c)swap(a,b),swap(id[0],id[1]);else if(c<a&&c<=b)swap(a,c),swap(id[0],id[2]);
	for(int i=0;i<n;i++)p[id[0][i]][tot[id[0][i]]][0]=id[1][i],p[id[0][i]][tot[id[0][i]]++][1]=id[2][i];
	s=b+c;t=b+c+1;ans=1e9;for(int i=0;i<(1<<a);i++)solve(i);cout<<ans<<endl;
}
int main(){
	for(int i=0;i<(1<<18);i++)cnt[i]=cnt[i>>1]+(i&1);for(cin>>T;T--;n=0,memset(tot,0,sizeof tot))cin>>a>>b>>c,get();
}
posted @ 2022-07-01 09:33  A_zjzj  阅读(35)  评论(0编辑  收藏  举报