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

 

posted @ 2018-02-07 09:58  CHerish_OI  阅读(147)  评论(0编辑  收藏  举报