BZOJ 4554 游戏 发表于 2017-03-26 | 更新于 2018-06-18 Link比较简单不写题解了 那为什么放上来呢? 因为有向图网络流反向边容量设成了与正向边相同查了挺长时间。 Code123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119#include "lucida"using std::fill;using std::copy;const int MAXN=50+5,MAXP=5000+11,MAXM=(MAXP<<1)+MAXP,INF=0x1f1f1f1f;const char BLANK='*',SOFT='x',HARD='#';struct Edge { int to,cap,v;Edge *pre,*rev; Edge(int to,int cap,Edge *pre):to(to),cap(cap),v(0),pre(pre) {} void *operator new(size_t) { static Edge *Me=alloc(Edge,MAXM<<1); return Me++; }}*G[MAXP];void Adde(int f,int t,int cap) { G[f]=new Edge(t,cap,G[f]); G[t]=new Edge(f,0,G[t]);//cap???? G[f]->rev=G[t]; G[t]->rev=G[f];}namespace isap { const int MAXN=MAXP; int s,t,n,d[MAXN],num[MAXN]; Edge *arc[MAXN],*pe[MAXN]; int Aug() { int minf=INF; for(Edge *e=pe[t];e;e=pe[e->rev->to]) { chkmn(minf,e->cap-e->v); } for(Edge *e=pe[t];e;e=pe[e->rev->to]) { e->v+=minf; e->rev->v-=minf; } return minf; } bool Advanced(int &cp) { for(Edge *&e=arc[cp];e;e=e->pre) { if(e->cap>e->v && d[cp]==d[e->to]+1) { pe[cp=e->to]=e; return 1; } } return 0; } int ISAP() { fill(d+s,d+t+1,0); fill(num,num+1+n,0); copy(G+s,G+t+1,arc+s); num[0]=n;int flow=0;pe[s]=0; for(int cp=s;d[s]<n;cp=cp==t?(flow+=Aug(),s):cp) { if(!Advanced(cp)) { if(!--num[d[cp]]) { break; } d[cp]=n; for(Edge *e=(arc[cp]=G[cp]);e;e=e->pre) { if(e->cap>e->v) { chkmn(d[cp],d[e->to]+1); } } cp=cp==s?cp:pe[cp]->rev->to; } } return flow; }}using isap::ISAP;int main() { freopen("input","r",stdin); //先搜出经过每个点的所有横长条和竖长条 //一个横长条只能配一个竖长条 static char map[MAXN][MAXN]; static int xi[MAXN][MAXN],yi[MAXN][MAXN]; int xic=0,yic=0,n,m; is>>n>>m; for(int x=1;x<=n;++x) { is>>(map[x]+1);//map[x].. } for(int x=1;x<=n;++x) { map[x][0]=map[x][m+1]=HARD; } for(int y=1;y<=m;++y) { map[0][y]=map[n+1][y]=HARD; } for(int x=1;x<=n;++x) { for(int y=1;y<=m;++y) { if(map[x][y]==HARD) { continue; } if(!xi[x][y]) { ++xic; for(int k=x;map[k][y]!=HARD;++k) { xi[k][y]=xic; } } if(!yi[x][y]) { ++yic; for(int k=y;map[x][k]!=HARD;++k) { yi[x][k]=yic; } } } } isap::s=0;isap::t=xic+yic+1;isap::n=isap::t+1; for(int i=1;i<=xic;++i) { Adde(isap::s,i,1); } for(int i=1;i<=yic;++i) { Adde(i+xic,isap::t,1); } for(int x=1;x<=n;++x) { for(int y=1;y<=m;++y) { if(map[x][y]==BLANK) { Adde(xi[x][y],yi[x][y]+xic,1); } } } int Ans=ISAP(); os<<Ans<<'\n'; return 0;}