bzoj1412(最小割)

1412: [ZJOI2009]狼和羊的故事

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 2091   Solved: 1088
[ Submit][ Status][ Discuss]

Description

“狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。 Orez想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。

Input

文件的第一行包含两个整数n和m。接下来n行每行m个整数,1表示该格子属于狼的领地,2表示属于羊的领地,0表示该格子不是任何一只动物的领地。

Output

文件中仅包含一个整数ans,代表篱笆的最短长度。

Sample Input

2 2
2 2
1 1

Sample Output

2

数据范围
10%的数据 n,m≤3
30%的数据 n,m≤20
100%的数据 n,m≤100

解题思路:
首先我们只看当前这个格子四周的值,也就是影响每一个格子的只有四周的值。那么,选狼或者是羊的所有格子与起点相连,另外一个与终点相连。再将 每个格子与四周相连,使得联系在一起。这样求一个最小割就可以。


#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,len=1,tail,head;
int to[500005];
int lg[500005];
int next[500005];
int h[500000];
int dis[10005];
int q[500000];
int ch[110][110];
int x1[5]={0,0,0,1,-1};
int x2[5]={0,1,-1,0,0};


inline int read()
 {
  char y; int x=0,f=1; y=getchar();
  while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}
  while (y>='0' && y<='9') {x=x*10+int (y)-48; y=getchar();}
  return x*f;
 }


void insert(int x,int y,int lt)
 {
  ++len; to[len]=y; lg[len]=lt; next[len]=h[x]; h[x]=len;
 }


bool bfs()
 {
  memset(dis,-1,sizeof(dis));
  dis[0]=0; tail=1; head=0; q[tail]=0;
  while (head<tail)
  {
  ++head;
  int u=h[q[head]];
  while (u!=0)
  {
  if (dis[to[u]]==-1 && lg[u]>0)
  {
  dis[to[u]]=dis[q[head]]+1;
  ++tail; q[tail]=to[u];
  }
  u=next[u];
  }
  }
  if (dis[n*m+1]!=-1) return true; else return false;
 }


int dinic(int o,int flow)
 {
  if (o==n*m+1) return flow;
    int used=0;
    int u=h[o];
    while (u!=0)
     {
      if (dis[to[u]]==dis[o]+1 && lg[u]>0)
      {
      int ss=dinic(to[u],min(flow-used,lg[u]));
      if (ss)
      {
      lg[u]-=ss;
      lg[u^1]+=ss;
      used+=ss;
      if (used==flow) return used;
      }
      }
      u=next[u];
     }
    if (used==0) dis[o]=-1; 
    return used;
 }


int main()
{
freopen("main.in","r",stdin);
freopen("me.out","w",stdout);
n=read(); m=read();
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
 {
  int x; x=read();
  if (x==1) {insert(0,(i-1)*m+j,0x7fffffff); insert((i-1)*m+j,0,0);}
  if (x==2) {insert((i-1)*m+j,n*m+1,0x7fffffff); insert(n*m+1,(i-1)*m+j,0);}
  ch[i][j]=x;
 }
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
 {
  if (ch[i][j]==1)
  {
    for (int k=1;k<=4;++k)
{
int u1=i+x1[k]; int u2=j+x2[k];
if (u1>0 && u1<=n && u2>0 && u2<=m &&(ch[u1][u2]==0 || ch[u1][u2]==2))
{
insert((i-1)*m+j,(u1-1)*m+u2,1); insert((u1-1)*m+u2,(i-1)*m+j,0);
}
}
  }else if (ch[i][j]==0)
   {
    for (int k=1;k<=4;++k)
{
int u1=i+x1[k]; int u2=j+x2[k];
if (u1>0 && u1<=n && u2>0 && u2<=m && (ch[u1][u2]==0 || ch[u1][u2]==2))
{
insert((i-1)*m+j,(u1-1)*m+u2,1); insert((u1-1)*m+u2,(i-1)*m+j,0);
}
}
   }
 }
int sum=0;
while (bfs())
{
sum+=dinic(0,0x7fffffff);
}
cout<<sum<<endl;
}

你可能感兴趣的:(bzoj1412(最小割))