1412: [ZJOI2009]狼和羊的故事
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 732 Solved: 406
[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
解析:
很容易看出是最小割。。。因为要将狼和羊分开
狼连原点,边权inf,羊连汇点,边权inf。。。
中间,狼到空地,狼到羊,空地到羊,连边,边权为1.。。。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define inf 1000000000
const int dx[4]={0,1,0,-1};
const int dy[4]={1,0,-1,0};
int n,m,s,t,map[110][110],l=0;
struct node
{
int u,v,c,next;
}edge[100000];
int head[100000];
int d[10010],sumd[10010];
void read()
{
freopen("wolf.in","r",stdin);
freopen("wolf.out","w",stdout);
}
void add(int u,int v,int c)
{
// printf("%d %d %d\n",u,v,c);
edge[l].u=u;
edge[l].v=v;
edge[l].c=c;
edge[l].next=head[u];
head[u]=l++;
edge[l].u=v;
edge[l].v=u;
edge[l].c=0;
edge[l].next=head[v];
head[v]=l++;
}
int sap(int u,int flow)
{
if(u==t)return flow;
int sum=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(edge[i].c && d[u]==d[v]+1)
{
int t=sap(v,min(edge[i].c,flow-sum));
sum+=t;
edge[i].c-=t;edge[i^1].c+=t;
if(sum==flow)return sum;
if(d[0]>=t)return sum;
}
}
sumd[d[u]]--;
if(sumd[d[u]]==0)d[0]=t+1;
++sumd[++d[u]];
return sum;
}
bool check(int x,int y)
{
if(1<=x&&x<=n&&y>=1&&y<=m)return 1; else return 0;
}
void work()
{
scanf("%d%d",&n,&m);
s=0;t=n*m+1;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&map[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
int cnt=(i-1)*m+j;
if(map[i][j]==1)
{
add(s,cnt,inf);
for(int k=0;k<4;k++)
{
int newx=i+dx[k];
int newy=j+dy[k];
if(check(newx,newy))
{
int nuk=(newx-1)*m+newy;
if(map[newx][newy]!=1)add(cnt,nuk,1);
}
}
}
if(map[i][j]==2)add(cnt,t,inf);
if(map[i][j]==0)
{
for(int k=0;k<4;k++)
{
int newx=i+dx[k];
int newy=j+dy[k];
if(check(newx,newy))
{
int nuk=(newx-1)*m+newy;
if(map[newx][newy]!=1)add(cnt,nuk,1);
}
}
}
}
int ans=0;
sumd[0]=t+1;
while(d[0]<=t)
ans+=sap(0,inf);
printf("%d\n",ans);
}
int main()
{
read();
work();
return 0;
}