「HNOI 2013」消毒
阿新 • • 發佈:2019-02-19
bits main nic dfs c++ getch register org lse
題目鏈接
戳我
\(Solution\)
我們首先想一想如果這一題只是二維的該怎麽辦?
就是一個最小點覆蓋問題.這裏就不詳細解釋了,用網絡流或匈牙利都無所謂.
但現在是三維的,那麽現在該如何處理呢?
我們發現\(a*b*c<=5000\),所以必定有一個要小於\(\sqrt[3]{5000}\)
所以我們可以枚舉最小的一維的狀態,那一維已經消了,還是沒消.
對於沒消的直接如同二維的跑最小點覆蓋就好了.
但是\(bzoj\)實在卡不過去
\(Code\)
#include<bits/stdc++.h> #define inf 1e9 using namespace std; typedef long long ll; int read(){ int x=0,f=1; char c=getchar(); while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar(); while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x*f; } #define re register struct node{ int to,next,v; }a[200001]; int S[100001],ss[100001],vis[100001],bj[50],bin[50],head[100001],dep[10001],cnt,n,m,s,t,x,y,z,A,B,C,res,Min,minx,tot,hh,maxx,cur[100010]; inline void add(re int x,re int y,re int c){ a[++cnt].to=y,a[cnt].next=head[x],a[cnt].v=c,head[x]=cnt; a[++cnt].to=x,a[cnt].next=head[y],a[cnt].v=0,head[y]=cnt; } queue<int> q; inline int bfs(){ for(int i=s;i<=t;i++) dep[i]=0; q.push(s); dep[s]=1; while(!q.empty()){ re int now=q.front(); q.pop(); for(re int i=head[now];i;i=a[i].next){ re int v=a[i].to; if(!dep[v]&&a[i].v>0) dep[v]=dep[now]+1,q.push(v); } } if(dep[t]) return 1; return 0; } int dfs(int k,int list) { if(k==t||!list) return list; int flow=0; for(int &i=cur[k]; i; i=a[i].next) { int v=a[i].to; if(dep[v]==dep[k]+1&&a[i].v) { int p=dfs(v,min(list,a[i].v)); if(p){ list-=p; flow+=p; a[i].v-=p; if(i%2) a[i+1].v+=p; else a[i-1].v+=p; if(!list) break; } } } if(!flow) dep[k]=-1; return flow; } inline int Dinic(int js){ re int k; while(bfs()){ for(re int i=0;i<=t;i++) cur[i]=head[i]; while((k=dfs(s,inf))){ js+=k; if(js>=Min) return js; } } return js; } struct node1 { int x,y,z; }b[5010]; inline void solve(re int x){ cnt=s=tot=maxx=0; re int ans=0; for(re int i=0;i<A;i++){ if(x&(1<<i)) ans++,bj[i+1]=0; else bj[i+1]=1; } for(re int i=1;i<=res;i++) if(bj[b[i].x]) S[++tot]=b[i].y,ss[tot]=b[i].z; for(re int i=1;i<=tot;i++) maxx=max(maxx,max(S[i],ss[i])); t=maxx*2+1; for(re int i=s;i<=t;i++) head[i]=0; for(re int i=1;i<=maxx;i++) add(s,i,1),add(i+maxx,t,1); for(re int i=1;i<=tot;i++) add(S[i],ss[i]+maxx,1); Min=min(Min,Dinic(ans)); } int main(){ int D=read(); bin[0]=1; for(re int i=1;i<=20;i++) bin[i]=bin[i-1]<<1; while(D--){ A=read(),B=read(),C=read(),minx=min(A,min(B,C)),res=0,Min=inf; if(B==minx) swap(A,B); else if(C==minx) swap(A,C); for(re int i=1;i<=A;i++) for(re int j=1;j<=B;j++) for(re int k=1;k<=C;k++){ x=read(); if(x) b[++res].x=i,b[res].y=j,b[res].z=k; } for(re int i=0;i<bin[A];i++) solve(i); printf("%d\n",Min); } }
「HNOI 2013」消毒