1412: [ZJOI2009]狼和羊的故事

Posted inwill

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1412: [ZJOI2009]狼和羊的故事相关的知识,希望对你有一定的参考价值。

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 4017  Solved: 2037
[Submit][Status][Discuss]

Description

“狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。 Orez想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。

Input

文件的第一行包含两个整数n和m。接下来n行每行m个整数,1表示该格子属于狼的领地,2表示属于羊的领地,0表示该格子不是任何一只动物的领地。

Output

文件中仅包含一个整数ans,代表篱笆的最短长度。

Sample Input

2 2
2 2
1 1

Sample Output

2

数据范围
10%的数据 n,m≤3
30%的数据 n,m≤20
100%的数据 n,m≤100
 
开始以为是最大染色之类的问题,查题解发现居然是最大流最小割
栅栏问题可以转换为,存在两个集合,之间不存在通路,正好符合最小割的定义
开始建图
从源点S连向狼,容量为INF
从羊连向汇点T,容量为INF
从狼连向相邻的羊和空地,容量为1
从空地连向相邻的羊和空地,容量为1
 
跑一边最大流,代码意外的简洁
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 
 7 #define get(i,j) ((i-1)*m+j)
 8 const int INF=0x7f7f7f7f;
 9 const int MAXN=400000;
10 const int xx[4]={-1,1,0,0},yy[4]={0,0,-1,1};
11 
12 struct Edge
13 {
14     int to,w,next;
15 }E[MAXN];
16 int node=1,head[MAXN],dis[MAXN],mp[200][200];
17 int s=0,t=10001;
18 int n,m,ans;
19 
20 void insert(int u,int v,int w)
21 {
22     E[++node]=(Edge){v,w,head[u]};
23     head[u]=node;
24     E[++node]=(Edge){u,0,head[v]};
25     head[v]=node;
26 }
27 
28 bool bfs()
29 {
30     memset(dis,-1,sizeof(dis));
31     queue<int> Q;
32     Q.push(s);
33     dis[s]=0;
34     while(!Q.empty())
35     {
36         int q=Q.front();Q.pop();
37         for(int i=head[q];i;i=E[i].next)
38             if(E[i].w&&dis[E[i].to]==-1)
39             {
40                 Q.push(E[i].to);
41                 dis[E[i].to]=dis[q]+1;
42             }
43     }
44     return dis[t]!=-1;
45 }
46 
47 int dfs(int x,int flow)
48 {
49     if(x==t) return flow;
50     int w,used=0;
51     for(int i=head[x];i;i=E[i].next)
52         if(E[i].w&&dis[E[i].to]==dis[x]+1)
53         {
54             w=flow-used;
55             w=dfs(E[i].to,min(w,E[i].w));
56             E[i].w-=w;
57             E[i^1].w+=w;
58             used+=w;
59             if(used==flow)return flow;
60         }
61     if(!used) dis[x]=-1;
62     return used;
63 }
64 
65 void dinic()
66 {
67     while(bfs()) ans+=dfs(s,INF);
68 }
69 
70 int main()
71 {
72     scanf("%d%d",&n,&m);
73     for(int i=1;i<=n;i++)
74         for(int j=1;j<=m;j++)
75         {
76             scanf("%d",&mp[i][j]);
77             if(mp[i][j]==1) insert(s,get(i,j),INF);
78             else if(mp[i][j]==2) insert(get(i,j),t,INF);
79         }
80     for(int i=1;i<=n;i++)
81         for(int j=1;j<=m;j++)
82             for(int k=0;k<4;k++)
83             {
84                 int x=i+xx[k],y=j+yy[k];
85                 if(x<1||x>n||y<1||y>m) continue;
86                 if(mp[i][j]!=1||mp[x][y]!=1)
87                     insert(get(i,j),get(x,y),1);
88             }
89     dinic();
90     printf("%d",ans);
91     return 0;
92 }

 

以上是关于1412: [ZJOI2009]狼和羊的故事的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1412[ZJOI2009]狼和羊的故事 最小割

1412: [ZJOI2009]狼和羊的故事

BZOJ 1412[ZJOI2009]狼和羊的故事

bzoj 1412: [ZJOI2009]狼和羊的故事

BZOJ 1412 [ZJOI2009]狼和羊的故事(最小割)

bzoj 1412 [ZJOI2009]狼和羊的故事 最小割建图