网络流/最小割
一开始我是将羊的区域看作连通块,狼的区域看作另一种连通块,S向每个羊连通块连一条无穷边,每个狼连通块向T连一条无穷边,连通块内部互相都是无穷边。其余是四连通的流量为1的边……然后WA了= =自己的数据和样例都过了……
然后orz了一下Hzwer,改成对每个羊/狼都单独连一条无穷边,分界线/0点周围 连容量1的边……AC……
/**************************************************************
Problem: 1412
User: Tunix
Language: C++
Result: Accepted
Time:232 ms
Memory:3224 kb
****************************************************************/ //BZOJ 1412
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=,M=,INF=~0u>>;
const int fx[]={,,,-},
fy[]={,,-,};
typedef long long LL;
/******************tamplate*********************/
int n,m,a[][];
struct edge{
int from,to,v;
};
inline int pack(int i,int j){ return (i-)*m+j; }
struct Net{
edge E[M];
int head[N],next[M],cnt;
bool vis[][];
void add(int x,int y,int v){
E[++cnt]=(edge){x,y,v};
next[cnt]=head[x]; head[x]=cnt;
E[++cnt]=(edge){y,x,};
next[cnt]=head[y]; head[y]=cnt;
}
int s,t,cur[N],d[N],Q[N];
void bfs(int x,int y){
rep(k,){
int tx=x+fx[k],ty=y+fy[k];
if (a[tx][ty]==a[x][y] &&!a[x][y])
add(pack(x,y),pack(tx,ty),);
if (a[tx][ty]!=a[x][y]&&a[tx][ty]!=-)
add(pack(x,y),pack(tx,ty),);
}
}
void init(){
n=getint();m=getint();
cnt=;
s=;t=n*m+;
int x,y;
memset(a,-,sizeof a);
memset(vis,,sizeof vis);
F(i,,n) F(j,,m) a[i][j]=getint();
F(i,,n) F(j,,m){
bfs(i,j);
if (a[i][j]==) add(s,pack(i,j),INF);
if (a[i][j]==) add(pack(i,j),t,INF);
}
}
bool mklevel(){
memset(d,-,sizeof d);
d[s]=;
int l=,r=-;
Q[++r]=s;
while(l<=r){
int x=Q[l++];
for(int i=head[x];i;i=next[i])
if (d[E[i].to]==- && E[i].v){
d[E[i].to]=d[x]+;
Q[++r]=E[i].to;
}
}
return d[t]!=-;
}
int dfs(int x,int a){
if (x==t||a==) return a;
int flow=;
for(int &i=cur[x];i && flow<a;i=next[i])
if (d[E[i].to]==d[x]+ && E[i].v){
int f=dfs(E[i].to,min(a-flow,E[i].v));
E[i].v-=f;
E[i^].v+=f;
flow+=f;
}
if (!flow) d[x]=-;
return flow;
}
int Dinic(){
int flow=;
while(mklevel()){
F(i,s,t) cur[i]=head[i];
flow+=dfs(s,INF);
}
return flow;
}
}G1;
int main(){
#ifndef ONLINE_JUDGE
freopen("1412.in","r",stdin);
freopen("1412.out","w",stdout);
#endif
G1.init();
printf("%d\n",G1.Dinic());
return ;
}