题目描述
“狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。 Orez想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。
输入输出格式
输入格式:
文件的第一行包含两个整数n和m。接下来n行每行m个整数,1表示该格子属于狼的领地,2表示属于羊的领地,0表示该格子不是任何一只动物的领地。
输出格式:
文件中仅包含一个整数ans,代表篱笆的最短长度。
输入输出样例
说明
数据范围
10%的数据 n,m≤3
30%的数据 n,m≤20
100%的数据 n,m≤100
最小割的模型
一开始傻逼了。。上来就把正解否定了。。
源点向狼连边
狼向羊连边(狼吃羊hhh)
羊向汇点连边
空地之间互相连边
狼向空地连边
空地向羊连边
#include<cstdio> #include<cstring> #include<queue> using namespace std; const int MAXN=200001,INF=2*1e9+10; inline char nc() { static char buf[MAXN],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++; } inline int read() { char c=nc();int x=0,f=1; while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=nc();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=nc();} return x*f; } int S=0,T=301; struct node { int u,v,flow,nxt; }edge[MAXN*20]; int head[MAXN],cur[MAXN],num=0; inline void add_edge(int x,int y,int z) { edge[num].u=x; edge[num].v=y; edge[num].flow=z; edge[num].nxt=head[x]; head[x]=num++; } inline void AddEdge(int x,int y,int z) { add_edge(x,y,z); add_edge(y,x,0); }int deep[MAXN]; inline bool BFS() { memset(deep,0,sizeof(deep)); deep[S]=1; queue<int>q; q.push(S); while(q.size()!=0) { int p=q.front(); q.pop(); for(int i=head[p];i!=-1;i=edge[i].nxt) if(!deep[edge[i].v]&&edge[i].flow) { deep[edge[i].v]=deep[p]+1;q.push(edge[i].v); if(edge[i].v==T) return 1; } } return deep[T]; } int DFS(int now,int nowflow) { if(now==T||nowflow<=0) return nowflow; int totflow=0; for(int &i=cur[now];i!=-1;i=edge[i].nxt) { if(deep[edge[i].v]==deep[now]+1&&edge[i].flow) { int canflow=DFS(edge[i].v,min(nowflow,edge[i].flow)); edge[i].flow-=canflow;edge[i^1].flow+=canflow; totflow+=canflow; nowflow-=canflow; if(nowflow<=0) break; } } return totflow; } int Dinic() { int ans=0; while(BFS()) { memcpy(cur,head,sizeof(head)); ans+=DFS(S,INF); } return ans; } int xx[6]={0,-1,+1,0,0},yy[6]={0,0,0,-1,+1}; int a[1001][1001],belong[1001][1001]; int N,M; int main() { #ifdef WIN32 freopen("a.in","r",stdin); #else #endif memset(head,-1,sizeof(head)); N=read();M=read();T=N*M+2; for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) a[i][j]=read(),belong[i][j]=(i-1)*M + j; for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) { if(a[i][j]==1) { AddEdge(S,belong[i][j],INF); for(int k=1;k<=4;k++) if( i+xx[k] >= 1 && i+xx[k] <= N && j+yy[k] >= 1 && j+yy[k]<=M && a[i][j] != a[i+xx[k]][j+yy[k]]) AddEdge(belong[i][j],belong[i+xx[k]][j+yy[k]],1); } else if(a[i][j]==2) { AddEdge(belong[i][j],T,INF); for(int k=1;k<=4;k++) if( i+xx[k] >= 1 && i+xx[k] <= N && j+yy[k] >= 1 && j+yy[k]<=M && a[i+xx[k]][j+yy[k]] == 0 ) AddEdge(belong[i+xx[k]][j+yy[k]],belong[i][j],1); } else { for(int k=1;k<=4;k++) if( i+xx[k] >= 1 && i+xx[k] <= N && j+yy[k] >= 1 && j+yy[k]<=M && a[i+xx[k]][j+yy[k]] == 0) AddEdge(belong[i][j],belong[i+xx[k]][j+yy[k]],1); } } printf("%d",Dinic()); return 0; }