bzoj 4554 游戏 Posted on 2019-07-08 | Views: 最大流. 比较明显是个网络流,考虑如何建模. 硬石头将每一行分成了若干块,每一块内最多放一个炸弹,每一列也同理.然后对每一行/列的块建出它们的点,每一块能通过的流量都是 $1$ .对于空地 $(x,y)$ ,就从 $(x,y)$ 所在的行块向 $(x,y)$ 所在的列块连流量为 $1$ 的边就好了. 再建出源汇点连上这些块,跑一个最大流即可. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144#include<bits/stdc++.h>using namespace std;typedef long long ll;inline int read(){ int out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh;}const int MAXN=5e3+10,MAXM=3e5+10,N=51;int n,m,Map[N][N],bx[N][N],by[N][N],tx=0,ty=0;const int inf=1e9;char buf[N];struct Edge{ int nx,to,flow;}E[MAXM];int head[MAXN],ecnt=-1;void addedge(int u,int v,int flow){ ++ecnt; E[ecnt].to=v; E[ecnt].nx=head[u]; E[ecnt].flow=flow; head[u]=ecnt;}void ins(int u,int v,int flow){ addedge(u,v,flow); addedge(v,u,0);}int trans(char c){ if(c=='*') return 0; if(c=='x') return 1; return 2;}int cur[MAXN],dis[MAXN],flow[MAXN],dep[MAXN];queue<int> q;bool bfs(int S,int T){ for(int i=1;i<=T;++i) cur[i]=head[i]; memset(dep,-1,sizeof dep); dep[S]=0; q.push(S); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=E[i].nx) { int v=E[i].to; if(dep[v]==-1 && E[i].flow) { dep[v]=dep[u]+1; q.push(v); } } } return dep[T]!=-1;}int dfs(int u,int T,int limit){ if(u==T || !limit) return limit; int f,Flow=0; for(int i=cur[u];i!=-1;i=E[i].nx) { cur[u]=i; int v=E[i].to; if(dep[v]==dep[u]+1 && (f=dfs(v,T,min(limit,E[i].flow)))) { Flow+=f; limit-=f; E[i].flow-=f; E[i^1].flow+=f; if(!limit) break; } } return Flow;}int Dinic(int S,int T){ int Maxflow=0; while(bfs(S,T)) Maxflow+=dfs(S,T,inf); return Maxflow;}void solve(){ for(int i=1;i<=n;++i) { ++tx; for(int j=1;j<=m;++j) { bx[i][j]=tx; if(Map[i][j]==2) ++tx; } } for(int j=1;j<=m;++j) { ++ty; for(int i=1;i<=n;++i) { by[i][j]=ty; if(Map[i][j]==2) ++ty; } } int S=tx+ty+1,T=tx+ty+2; for(int i=1;i<=tx;++i) ins(S,i,1); for(int i=1;i<=ty;++i) ins(i+tx,T,1); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(!Map[i][j]) ins(bx[i][j],by[i][j]+tx,1); cout<<Dinic(S,T)<<endl;}int main(){ memset(head,-1,sizeof head); n=read(),m=read(); for(int i=1;i<=n;++i) { scanf("%s",buf+1); for(int j=1;j<=m;++j) Map[i][j]=trans(buf[j]); } solve(); return 0;}