【题目】
题目描述:
“ “ “狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向...... ” ” ”
Orez 听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干!
Orez 的羊狼圈可以看作一个 n × m n\times m n×m 个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是 Drake 很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以 Orez 决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。
通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。
Orez 想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。
输入格式:
文件的第一行包含两个整数 n n n 和 m m m。接下来 n n n 行每行 m m m 个整数, 1 1 1 表示该格子属于狼的领地, 2 2 2 表示属于羊的领地, 0 0 0 表示该格子不是任何一只动物的领地。
输出格式:
文件中仅包含一个整数 a n s ans ans,代表篱笆的最短长度。
样例数据:
输入
2 2
2 2
1 1
输出
2
数据范围:
10
%
10\%
10% 的数据,
n
,
m
≤
3
n,m≤3
n,m≤3
30
%
30\%
30% 的数据 ,
n
,
m
≤
20
n,m≤20
n,m≤20
100
%
100\%
100% 的数据,
n
,
m
≤
100
n,m≤100
n,m≤100
【分析】
妙啊,完全没想到网络流
从源点向每只羊连边,从每只狼向汇点连边,然后每个格子向四周连边
由于狼和羊要隔开,就相当于求一个割,由于又是最小的割,跑一遍最大流就可以了
【代码】
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 10005
#define M 1000005
#define inf (1ll<<31ll)-1
using namespace std;
int n,m,s,t,tot=1;
int v[M],w[M],nxt[M];
int f[N],d[N],first[N];
int tx[5]={0,0,0,1,-1},ty[5]={0,1,-1,0,0};
int id(int i,int j){return (i-1)*m+j;}
void add(int x,int y,int f)
{
nxt[++tot]=first[x];
first[x]=tot,v[tot]=y,w[tot]=f;
}
bool bfs(int s)
{
int x,y,i;
memset(d,-1,sizeof(d));
memcpy(f,first,sizeof(f));
queue<int>q;q.push(s);d[s]=0;
while(!q.empty())
{
x=q.front();q.pop();
for(i=f[x];i;i=nxt[i])
{
y=v[i];
if(w[i]&&d[y]==-1)
{
d[y]=d[x]+1;
q.push(y);
}
}
}
return d[t]!=-1;
}
int dinic(int now,int flow)
{
if(now==t) return flow;
int x,ans=0,delta;
for(int &i=f[now];i;i=nxt[i])
{
x=v[i];
if(d[x]==d[now]+1&&w[i])
{
delta=dinic(x,min(flow,w[i]));
w[i]-=delta,w[i^1]+=delta;
flow-=delta,ans+=delta;
if(!flow) return ans;
}
}
return ans;
}
int main()
{
int i,j,k,x,ans=0;
scanf("%d%d",&n,&m);
s=0,t=n*m+1;
for(i=1;i<=n;++i){
for(j=1;j<=m;++j){
scanf("%d",&x);
if(x==1) add(s,id(i,j),inf),add(id(i,j),s,0);
if(x==2) add(id(i,j),t,inf),add(t,id(i,j),0);
}
}
for(i=1;i<=n;++i){
for(j=1;j<=m;++j){
for(k=1;k<=4;++k){
int x=i+tx[k];
int y=j+ty[k];
if(x>=1&&x<=n&&y>=1&&y<=m)
add(id(i,j),id(x,y),1),add(id(x,y),id(i,j),0);
}
}
}
while(bfs(s)) ans+=dinic(s,inf);
printf("%d",ans);
return 0;
}