1412: [ZJOI2009]狼和羊的故事
Posted inwill
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1412: [ZJOI2009]狼和羊的故事相关的知识,希望对你有一定的参考价值。
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
2 2
1 1
Sample Output
2
数据范围
10%的数据 n,m≤3
30%的数据 n,m≤20
100%的数据 n,m≤100
数据范围
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]狼和羊的故事的主要内容,如果未能解决你的问题,请参考以下文章