[bzoj1412]狼和羊的故事

题意是需要在某些相邻的节点中建立栅栏使得这两个点不能直接走到,使得所有狼的领地和羊的领地两两不能(间接)走到最少需要多少栅栏。

很显然,将S向所有羊连边,狼向T连边(流量为inf),然后任意相邻两个点连边(羊/狼之间可以不连),求最小割即可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 10005
 4 #define id (i-1)*m+j
 5 #define inf 0x3f3f3f3f
 6 struct ji{
 7     int nex,to,len;
 8 }edge[N*10];
 9 queue<int>q;
10 int E,n,m,p,head[N],work[N],d[N];
11 void add(int x,int y,int z){
12     edge[E].nex=head[x];
13     edge[E].to=y;
14     edge[E].len=z;
15     head[x]=E++;
16     if (E&1)add(y,x,0);
17 }
18 bool bfs(){
19     memset(d,-1,sizeof(d));
20     q.push(0);
21     d[0]=0;
22     while (!q.empty()){
23         int k=q.front();
24         q.pop();
25         for(int i=head[k];i!=-1;i=edge[i].nex)
26             if ((edge[i].len)&&(d[edge[i].to]<0)){
27                 d[edge[i].to]=d[k]+1;
28                 q.push(edge[i].to);
29             }
30     }
31     return d[n*m+1]>=0;
32 }
33 int dfs(int k,int s){
34     if (k>n*m)return s;
35     for(int &i=work[k];i!=-1;i=edge[i].nex)
36         if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){
37             int p=dfs(edge[i].to,min(s,edge[i].len));
38             if (p){
39                 edge[i].len-=p;
40                 edge[i^1].len+=p;
41                 return p;
42             }
43         }
44     return 0;
45 }
46 int dinic(){
47     int k,ans=0;
48     while (bfs()){
49         memcpy(work,head,sizeof(head));
50         while (k=dfs(0,inf))ans+=k;
51     }
52     return ans;
53 }
54 int main(){
55     scanf("%d%d",&n,&m);
56     memset(head,-1,sizeof(head));
57     for(int i=1;i<=n;i++)
58         for(int j=1;j<=m;j++){
59             scanf("%d",&p);
60             if (p==1)add(0,id,inf);
61             if (p==2)add(id,n*m+1,inf);
62             if (j>1)add(id,id-1,1);
63             if (j<m)add(id,id+1,1);
64             if (i>1)add(id,id-m,1);
65             if (i<n)add(id,id+m,1);
66         }
67     printf("%d",dinic());
68 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/11249096.html