【HNOI2013】消毒

题面

https://www.luogu.org/problem/P3231

题解

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define ri register int
#define N 5050
#define INF 1000000007
using namespace std;

inline int read() {
  int f=0,ret=0; char ch=getchar();
  while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar();
  while (ch>='0'&& ch<='9') ret=ret*10+(ch-'0'),ch=getchar();
  return f?-ret:ret;
}

int T,a,b,c,cc;
int A,B,C;
int x[N],y[N],z[N];
int mi;

int count(int x) {
  int ret=0;
  for (ri i=0;i<=20;i++) if (x&(1<<i)) ret++;
  return ret;
}

struct graph {
  vector<int> ed[N];
  vector<int> w,to;
  int cur[N];
  int d[N];
  int cnt;
  
  void add_edge(int a,int b,int c) {
    ed[a].push_back(++cnt); to.push_back(b); w.push_back(c);
    ed[b].push_back(++cnt); to.push_back(a); w.push_back(0);
  }
  
  bool bfs() {
    for (ri i=0;i<=B+C+1;i++) d[i]=INF;
    queue<int> q;
    d[0]=0;
    q.push(0);
    while (!q.empty()) {
      int x=q.front(); q.pop();
      for (ri i=0;i<ed[x].size();i++) {
        int e=ed[x][i];
        if (w[e] && d[to[e]]>d[x]+1) {
          d[to[e]]=d[x]+1;
          q.push(to[e]);
        }
      }
    }
    return d[B+C+1]<=10000;
  }
  
  int dfs(int x,int limit) {
    if (x==B+C+1 || !limit) return limit;
    int tot=0;
    for (ri &i=cur[x];i<ed[x].size();i++) {
      int e=ed[x][i];
      if (d[to[e]]!=d[x]+1 || !w[e]) continue;
      int f=dfs(to[e],min(limit,w[e]));
      if (!f) continue;
      w[e]-=f; w[1^e]+=f; limit-=f; tot+=f;
      if (!limit) return tot;
    }
    return tot;
  }
  
  int dinic() {
    int ret=0;
    while (bfs()) {
      for (ri i=0;i<=B+C+1;i++) cur[i]=0;
      ret+=dfs(0,INF);
    }
    return ret;
  }
  
  int mf(int s) {
    w.clear(); to.clear();
    for (ri i=0;i<=B+C+1;i++) ed[i].clear();
    cnt=-1;
    for (ri i=1;i<=cc;i++) if (!(s&(1<<(x[i]-1)))) add_edge(y[i],z[i]+B,1);
    for (ri i=1;i<=B;i++) add_edge(0,i,1);
    for (ri i=B+1;i<=B+C;i++) add_edge(i,B+C+1,1);
    return dinic();
  }
} g;

using namespace std;

int main() {
  T=read();
  while (T--) {
    a=read(); b=read(); c=read();
    mi=1;
    if (b<a && b<c) mi=2; else if (c<a && c<b) mi=3;
    cc=0;
    for (ri i=1;i<=a;i++) {
      for (ri j=1;j<=b;j++) {
        for (ri k=1;k<=c;k++) {
          int w=read();
          if (!w) continue;
          if (mi==2) {
            x[++cc]=j,y[cc]=i,z[cc]=k;
          }
          else if (mi==3) {
            x[++cc]=k,y[cc]=j,z[cc]=i;
          }
          else 
            x[++cc]=i,y[cc]=j,z[cc]=k;
        }
      }
    }
    A=a,B=b,C=c;
    if (mi==2) swap(A,B); else if (mi==3) swap(A,C);
    int ans=A+B+C;
    for (ri i=0;i<(1<<A);i++) {
      int t=count(i)+g.mf(i);
      if (t<ans) ans=t;
    }
    cout<<ans<<endl;
  }
}

 

posted @ 2019-07-31 19:37  HellPix  阅读(97)  评论(0编辑  收藏  举报