【bzoj】 1412: [ZJOI2009]狼和羊的故事
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集和T集不存在通路。而题目又要求建的栅栏最少,于是就是最小割问题了。
主要是建边 从源点连向狼的无穷边
从羊向汇点的无穷边
再是狼到空地和羊
空地到空地和羊
1 #include<queue> 2 #include<cstdio> 3 #include<iostream> 4 #define MAXN 100010 5 6 const int INF=0x7fffffff; 7 8 using namespace std; 9 10 int map[101][101]; 11 12 int n,m,st,en,ans; 13 14 int x[4]={0,1,0,-1}; 15 int y[4]={1,0,-1,0}; 16 17 struct node { 18 int to; 19 int next; 20 int val; 21 }; 22 node e[MAXN]; 23 24 int head[MAXN],tot=1; 25 26 int depth[MAXN],cur[MAXN]; 27 28 queue<int> q; 29 30 inline void read(int&x) { 31 int f=1;x=0;char c=getchar(); 32 while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();} 33 while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-48;c=getchar();} 34 x=x*f; 35 } 36 37 inline void add(int x,int y,int val) { 38 e[++tot].to=y; 39 e[tot].val=val; 40 e[tot].next=head[x]; 41 head[x]=tot; 42 } 43 44 inline int bfs() { 45 for(int i=0;i<=en;i++) cur[i]=head[i],depth[i]=-1; 46 while(!q.empty()) q.pop(); 47 q.push(st);depth[st]=0; 48 while(!q.empty()) { 49 int u=q.front(); 50 q.pop(); 51 for(int i=head[u];i!=0;i=e[i].next) { 52 int to=e[i].to; 53 if(e[i].val>0&&depth[to]==-1) { 54 depth[to]=depth[u]+1; 55 q.push(to); 56 if(to==en) return true; 57 } 58 } 59 } 60 return false; 61 } 62 63 inline int dinic(int now,int flow) { 64 if(now==en) return flow; 65 int rest=0,delat; 66 for(int & i=cur[now];i!=0;i=e[i].next) { 67 int to=e[i].to; 68 if(depth[to]==depth[now]+1&&e[i].val>0) { 69 delat=dinic(to,min(e[i].val,flow-rest)); 70 if(delat) { 71 e[i].val-=delat; 72 e[i^1].val+=delat; 73 rest+=delat; 74 if(rest==flow) break; 75 } 76 } 77 } 78 if(flow!=rest) depth[now]=-1; 79 return rest; 80 } 81 82 int main() { 83 read(n);read(m); 84 en=n*m+1; 85 for(int i=1;i<=n;i++) 86 for(int j=1;j<=m;j++) { 87 read(map[i][j]); 88 if(map[i][j]==1) add(st,(i-1)*m+j,INF),add((i-1)*m+j,st,0); 89 else if(map[i][j]==2) add((i-1)*m+j,en,INF),add(en,(i-1)*m+j,0); 90 } 91 for(int i=1;i<=n;i++) 92 for(int j=1;j<=m;j++) 93 for(int k=0;k<4;k++) { 94 int xx=i+x[k]; 95 int yy=j+y[k]; 96 if(xx<1||yy<1||xx>n||yy>m||map[i][j]==2) continue; 97 if(map[xx][yy]!=1) add((i-1)*m+j,(xx-1)*m+yy,1),add((xx-1)*m+yy,(i-1)*m+j,0); 98 } 99 while(bfs()) ans+=dinic(st,INF); 100 printf("%d\n",ans); 101 return 0; 102 }
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现