标签:sizeof gre problems 成长 for break turn php ace
很裸的最小割模型了。把狼和羊分开即可。
S向狼连容量无穷边,羊向T连容量无穷边。
狼向周围空地和羊连容量1的边,空地向周围空地和羊连容量1边。
最小割后,和S连的点即表示狼的领地,与T相连的点表示羊的领地。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define ll long long
#define inf 0x3f3f3f3f
#define N 105
using namespace std;
int n,m,S,T,tot,mp[N][N],hd[N*N],cur[N*N],d[N*N],vis[N*N];
int dx[]={0,0,1,-1};int dy[]={1,-1,0,0};
struct edge{int v,cap,next;}e[N*N*8];
int get(int i,int j){return (i-1)*m+j;}
bool check(int i,int j){return i>=1&&i<=n&&j>=1&&j<=m;}
void adde(int u,int v,int c){
e[tot].v=v;
e[tot].next=hd[u];
e[tot].cap=c;
hd[u]=tot++;
}
bool bfs(){
queue<int>q;
memset(vis,0,sizeof(vis));
d[S]=0;q.push(S);vis[S]=1;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=hd[u];~i;i=e[i].next){
int v=e[i].v;
if(e[i].cap<=0||vis[v])continue;
d[v]=d[u]+1;vis[v]=1;q.push(v);
}
}
return vis[T];
}
int dfs(int u,int a){
if(u==T||!a)return a;
int fl=0,f;
for(int &i=cur[u];~i;i=e[i].next){
if(e[i].cap<=0)continue;
int v=e[i].v;
if(d[v]==d[u]+1&&(f=dfs(v,min(a,e[i].cap)))){
fl+=f;a-=f;e[i].cap-=f;
e[i^1].cap+=f;if(!a)break;
}
}
return fl;
}
int main(){
#ifdef wsy
freopen("data.in","r",stdin);
#else
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
#endif
scanf("%d%d",&n,&m);
memset(hd,-1,sizeof(hd));
S=0;T=n*m+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d",&mp[i][j]);
if(mp[i][j]==1)adde(S,get(i,j),inf),adde(get(i,j),S,0);
else if(mp[i][j]==2)adde(get(i,j),T,inf),adde(T,get(i,j),0);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(mp[i][j]==2)continue;
int idx=get(i,j);
for(int k=0;k<4;k++){
int nx=i+dx[k],ny=j+dy[k];
if(!check(nx,ny))continue;
int nid=get(nx,ny);
if(mp[i][j]==1){
if(mp[nx][ny]!=1)adde(idx,nid,1),adde(nid,idx,0);
}
else if(mp[nx][ny]!=1)adde(idx,nid,1),adde(nid,idx,0);
}
}
int ans=0;
while(bfs()){
for(int i=S;i<=T;i++)cur[i]=hd[i];
ans+=dfs(S,0x3f3f3f3f);
}
printf("%d",ans);
return 0;
}
标签:sizeof gre problems 成长 for break turn php ace
原文地址:http://www.cnblogs.com/wsy01/p/7932157.html