bzoj1412: [ZJOI2009]狼和羊的故事(最小割)
1412: [ZJOI2009]狼和羊的故事
题目:传送门
题解:
一道最小割的基础水题。。。
基本建模啊:
st连羊,狼连ed,空地和羊狼连边,羊和空地和狼连边
跑一遍dicnic就出答案了
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 const int dx[5]={0,-1,1,0,0}; 8 const int dy[5]={0,0,0,-1,1}; 9 struct node 10 { 11 int x,y,c,next,other; 12 }a[210000];int len,last[110000]; 13 int n,m,st,ed,head,tail; 14 int map[110][110]; 15 void ins(int x,int y,int c) 16 { 17 int k1,k2; 18 k1=++len; 19 a[len].x=x;a[len].y=y;a[len].c=c; 20 a[len].next=last[x];last[x]=len; 21 22 k2=++len; 23 a[len].x=y;a[len].y=x;a[len].c=0; 24 a[len].next=last[y];last[y]=len; 25 26 a[k1].other=k2; 27 a[k2].other=k1; 28 } 29 int h[110000],list[110000]; 30 bool bfs() 31 { 32 memset(h,0,sizeof(h));h[st]=1; 33 head=1;tail=2;list[1]=st; 34 while(head!=tail) 35 { 36 int x=list[head]; 37 for(int k=last[x];k;k=a[k].next) 38 { 39 int y=a[k].y; 40 if(h[y]==0 && a[k].c) 41 { 42 h[y]=h[x]+1; 43 list[tail++]=y; 44 } 45 } 46 head++; 47 } 48 if(h[ed])return true; 49 return false; 50 } 51 int find_flow(int x,int flow) 52 { 53 if(x==ed)return flow; 54 int s=0,t; 55 for(int k=last[x];k;k=a[k].next) 56 { 57 int y=a[k].y; 58 if(h[y]==h[x]+1 && a[k].c>0 && flow>s) 59 { 60 s+=t=find_flow(y,min(a[k].c,flow-s)); 61 a[k].c-=t;a[a[k].other].c+=t; 62 } 63 } 64 if(s==0)h[x]=0; 65 return s; 66 } 67 int d[110][110]; 68 int main() 69 { 70 scanf("%d%d",&n,&m); 71 len=0;memset(last,0,sizeof(last)); 72 st=n*m+1;ed=st+1;int ss=0; 73 for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)d[i][j]=++ss; 74 memset(map,-1,sizeof(map)); 75 for(int i=1;i<=n;i++) 76 for(int j=1;j<=m;j++) 77 { 78 scanf("%d",&map[i][j]); 79 if(map[i][j]==1)ins(st,d[i][j],999999999); 80 else if(map[i][j]==2)ins(d[i][j],ed,999999999); 81 } 82 for(int i=1;i<=n;i++) 83 for(int j=1;j<=m;j++) 84 { 85 if(map[i][j]==1 || map[i][j]==0) 86 for(int k=1;k<=4;k++) 87 { 88 int ti=i+dx[k],tj=j+dy[k]; 89 if(map[ti][tj]==2 || map[ti][tj]==0) 90 ins(d[i][j],d[ti][tj],1); 91 } 92 } 93 int ans=0; 94 while(bfs())ans+=find_flow(st,999999999); 95 printf("%d\n",ans); 96 return 0; 97 }