洛谷 P2472 [SCOI2007] 蜥蜴 / YbtOJ「图论」第2章 网络流初探 F. 蜥蜴逃离 题解--zhengjun
作者:互联网
思路
显然直接建图跑个最大流,答案就是总蜥蜴数减掉最大流。
但是由于有高度的限制,也就是每个地方只能被走一定数量,还要加一些限制。
所以把每个点拆成入点和出点,从入点向出点连一条流量为 \(h_{i,j}\) 的边。
再枚举出每个格子能跳到的其他格子,从当前格子的出点向其他能跳到的格子的入点连一条 \(+\infty\) 的边。
然后从源点 \(s\) 向每个蜥蜴所在的位置连一条流量为 \(1\) 的边。
从每个能够一步跳出去的点向汇点 \(t\) 连一条 \(+\infty\) 的边。
注意上面两个 \(+\infty\) 比较容易出问题,因为每个点可能有很多蜥蜴都要经过。
代码
#include<bits/stdc++.h>
using namespace std;typedef long long ll;const int N=25,M=N*N*2,K=M*M,inf=1e9;char a[N][N],b[N][N];
int n,m,k,s,t,cnt,h[N][N],head[M],kk=1,d[M],cur[M];struct edges{int to,c,nex;}edge[K];
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;}
int id(int x,int y){return (x-1)*m+y;}
bool check(int x,int y){return x*x+y*y<=k*k;}
bool bfs(){
queue<int>q;q.push(s);memset(d,-1,sizeof d);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)q.push(v),d[v]=d[u]+1,cur[v]=head[v];
}return ~d[t];
}
int dfs(int u,int lim=inf){
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;}
int main(){
scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=n;i++)scanf("%s",a[i]+1);for(int i=1;i<=n;i++)scanf("%s",b[i]+1);
s=0;t=n*m*2+1;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(a[i][j]>'0'){
add(id(i,j),id(i,j)+n*m,a[i][j]-'0');b[i][j]=='L'&&(add(s,id(i,j),1),++cnt);
if(min(min(min(i,j),n-i+1),m-j+1)<=k)add(id(i,j)+n*m,t,inf);for(int ii=1;ii<=n;ii++)
for(int jj=1;jj<=m;jj++)if(a[ii][jj]>'0')if(check(i-ii,j-jj)&&(i^ii||j^jj))add(id(i,j)+n*m,id(ii,jj),inf);
}cout<<cnt-dinic();return 0;
}
标签:head,洛谷,int,题解,kk,add,edge,蜥蜴,id 来源: https://www.cnblogs.com/A-zjzj/p/16434220.html