BZOJ 1412: [ZJOI2009]狼和羊的故事【最小割】
1412: [ZJOI2009]狼和羊的故事
【题目描述】
传送门
【题解】
典型的最小割,那么怎么建图呢?
首先肯定要建超级源和汇,然后肯定狼向羊建边(反过来也可以),若有空的的话就是(狼->空->空->羊)按照这个顺序建边就可以了。
代码如下
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int flg[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int hd,tl,n,m,a[105][105],S,T,dep[10005],que[10005];
int tot=-1,lnk[10005],nxt[2*40005],son[2*40005],W[2*40005];
void add(int x,int y,int w){son[++tot]=y;nxt[tot]=lnk[x];lnk[x]=tot;W[tot]=w;}
int CHG(int x,int y){return (x-1)*m+y;}
bool check(int x,int y){if(x<1||x>n||y<1||y>m) return 0;return 1;}
bool BFS(){
memset(dep,0,sizeof(dep));dep[S]=1;
hd=0,que[tl=1]=S;
while(hd!=tl){
int x=que[++hd];
for(int j=lnk[x];j^-1;j=nxt[j])
if(!dep[son[j]]&&W[j]>0) dep[son[j]]=dep[x]+1,que[++tl]=son[j];
}
return dep[T];
}
int DFS(int x,int flow){
if(x==T) return flow;
int now=0;
for(int j=lnk[x];j^-1;j=nxt[j])
if((dep[son[j]]==dep[x]+1)&&W[j]>0){
int y=DFS(son[j],min(flow,W[j]));
if(y>0){W[j]-=y;W[j^1]+=y;now+=y;if(now==flow) return flow;}
}
if(!now) dep[x]=0;
return now;
}
int Dinic(){
int ans=0;
while(BFS())
while(int t=DFS(S,1e9)) ans+=t;
return ans;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("prob.in","r",stdin);
freopen("prob.out","w",stdout);
#endif
scanf("%d%d",&n,&m);S=0,T=n*m+1;
memset(lnk,-1,sizeof(lnk));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
if(a[i][j]==2) add(S,CHG(i,j),1e9),add(CHG(i,j),S,0);
if(a[i][j]==1) add(CHG(i,j),T,1e9),add(T,CHG(i,j),0);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=0;k<4;k++)
if(check(i+flg[k][0],j+flg[k][1])){
if(a[i][j]==2&&a[i+flg[k][0]][j+flg[k][1]]==1)
add(CHG(i,j),CHG(i+flg[k][0],j+flg[k][1]),1),add(CHG(i+flg[k][0],j+flg[k][1]),CHG(i,j),0);
if(a[i][j]==2&&a[i+flg[k][0]][j+flg[k][1]]==0)
add(CHG(i,j),CHG(i+flg[k][0],j+flg[k][1]),1),add(CHG(i+flg[k][0],j+flg[k][1]),CHG(i,j),0);
if(a[i][j]==0&&a[i+flg[k][0]][j+flg[k][1]]==0)
add(CHG(i,j),CHG(i+flg[k][0],j+flg[k][1]),1),add(CHG(i+flg[k][0],j+flg[k][1]),CHG(i,j),0);
if(a[i][j]==0&&a[i+flg[k][0]][j+flg[k][1]]==1)
add(CHG(i,j),CHG(i+flg[k][0],j+flg[k][1]),1),add(CHG(i+flg[k][0],j+flg[k][1]),CHG(i,j),0);
}
printf("%d\n",Dinic());
return 0;
}