[BZOJ1412/Luogu2598][ZJOI2009]狼和羊的故事
阿新 • • 發佈:2019-01-01
add bool != d+ main continue 。。 比較 problem
題目鏈接:
BZOJ1412
Luogu2598
題意好迷。。
一個比較簡單的最小割模型。
對於所有狼與源點連邊,羊與匯點連邊,容量\(+\infty\)。
對於每個點向四周連邊,容量為\(1\),代表聯通。
然後跑一遍最小割就行了(羊和狼聯通則有\(1\)流量,相當於建柵欄)。
#include <cstdio> #include <cstring> #define ID(x,y) (((x)-1)*m+y) inline int Min(int a,int b){return a<b?a:b;} inline int Max(int a,int b){return a>b?a:b;} int n,m,St,Ed; int Head[10005],Next[150005],To[150005],Val[150005],En=1; int Dis[10005],Pre[10005],Cur[10005],Cnt[10005]; const int Inf=0x3f3f3f3f,nx[]={-1,1,0,0},ny[]={0,0,-1,1}; inline void Add(int x,int y,int z) { Next[++En]=Head[x],To[Head[x]=En]=y,Val[En]=z; Next[++En]=Head[y],To[Head[y]=En]=x,Val[En]=0; } int Augment() { int Res=Inf; for(int x=Ed;x!=St;x=To[Pre[x]^1])Res=Min(Res,Val[Pre[x]]); for(int x=Ed,i;x!=St;x=To[i^1])Val[i=Pre[x]]-=Res,Val[i^1]+=Res; return Res; } int ISAP() { memcpy(Cur,Head,sizeof Cur); Cnt[0]=Ed; int Flow=0,x=St; while(Dis[St]<Ed) { if(x==Ed)Flow+=Augment(),x=St; bool Flag=false; for(int i=Cur[x],y;i;i=Next[i]) if(Val[i]&&Dis[y=To[i]]+1==Dis[x]) Flag=true,Cur[x]=Pre[y]=i,x=y,i=0; if(Flag)continue; int Wd=Ed-1; for(int i=Head[x];i;i=Next[i]) if(Val[i])Wd=Min(Wd,Dis[To[i]]); if(!--Cnt[Dis[x]])break; ++Cnt[Dis[x]=Wd+1],Cur[x]=Head[x]; if(x!=St)x=To[Pre[x]^1]; } return Flow; } int main() { scanf("%d%d",&n,&m),St=n*m+1,Ed=St+1; for(int i=1;i<=n;++i) for(int j=1,x;j<=m;++j) { scanf("%d",&x); if(x==1)Add(St,ID(i,j),Inf); else if(x==2)Add(ID(i,j),Ed,Inf); for(int k=0;k<4;++k) { int wx=i+nx[k],wy=j+ny[k]; if(wx>=1&&wx<=n&&wy>=1&&wy<=m)Add(ID(i,j),ID(wx,wy),1); } } printf("%d\n",ISAP()); return 0; }
[BZOJ1412/Luogu2598][ZJOI2009]狼和羊的故事