bzoj 1412 狼和羊的故事

题目大意:

将一个矩阵中的1和2分隔,求出最小的分隔代价

思路:

直接连边 所有点向四连块连边 其实也可以

正常的做法是狼到相邻的羊和空地,空地到相邻的空地和羊连一条流量为1的边

最后dinic

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #define inf 2139062143
10 #define ll long long
11 #define MAXN 10101
12 using namespace std;
13 inline int read()
14 {
15     int x=0,f=1;char ch=getchar();
16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 int n,m,a[MAXN/100][MAXN/100];
21 int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
22 struct dinic 
23 {
24     int fst[MAXN],nxt[MAXN<<4],to[MAXN<<4],val[MAXN<<4],cnt,s,t;
25     void mem() {memset(fst,0xff,sizeof(fst));cnt=-1;}
26     void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
27     int vis[MAXN],tot,cur[MAXN],dep[MAXN],q[MAXN];
28     int bfs()
29     {
30         int l=1,r=0;
31         memset(dep,0xff,sizeof(dep));
32         vis[t]=++tot,q[++r]=t;
33         while(l<=r)
34         {
35             int x=q[l++];
36             for(int i=fst[x];i!=-1;i=nxt[i])
37                 if(val[i^1]&&vis[to[i]]!=tot) 
38                 {
39                     //cout<<x<<" "<<to[i]<<endl;
40                     vis[to[i]]=tot,dep[to[i]]=dep[x]+1,q[++r]=to[i];
41                     if(to[i]==s) return 1;
42                 }
43         }
44         return vis[s]==tot;
45     }
46     int dfs(int x,int a)
47     {
48         if(x==t||!a) return a;
49         int flow=0,f;
50         for(int& i=cur[x];i!=-1;i=nxt[i])
51         {
52             if(val[i]&&dep[to[i]]==dep[x]-1&&(f=dfs(to[i],min(a,val[i]))))
53             {
54                 val[i]-=f,val[i^1]+=f,flow+=f,a-=f;
55                 if(!a) break;
56             }
57         }
58         return flow;
59     }
60     int solve()
61     {
62         int ans=0;int f;
63         while(bfs())
64         {
65             for(int i=0;i<=n*m+1;i++) cur[i]=fst[i];
66             //cout<<f<<" "<<ans<<endl;
67             while(f=dfs(s,inf)) ans+=f;
68         }
69         return ans;
70     }
71 }D;
72 int main()
73 {
74     n=read(),m=read(),D.s=0,D.t=n*m+1;
75     memset(a,0xff,sizeof(a));
76     D.mem();
77     for(int i=1;i<=n;i++)
78         for(int j=1;j<=m;j++) a[i][j]=read();
79     for(int i=1;i<=n;i++)
80         for(int j=1;j<=m;j++)
81         {
82             if(a[i][j]==1) D.add(0,(i-1)*m+j,inf),D.add((i-1)*m+j,0,0);
83             else if(a[i][j]==2) D.add((i-1)*m+j,D.t,inf),D.add(D.t,(i-1)*m+j,0);
84             for(int k=0;k<4;k++)
85             {
86                 int xx=i+dx[k],yy=j+dy[k];
87                 if(xx<1||xx>n||yy<1||yy>m||a[i][j]==2) continue;
88                 if(a[i][j]!=1||a[xx][yy]!=1) D.add(i*m-m+j,xx*m-m+yy,1),D.add(xx*m-m+yy,i*m-m+j,0);
89             }
90         }
91     printf("%d",D.solve());
92 }
View Code

 

posted @ 2018-02-09 08:39  jack_yyc  阅读(171)  评论(0编辑  收藏  举报