1412: [ZJOI2009]狼和羊的故事

Time Limit: 10 Sec  Memory Limit: 162 MB

Submit: 3454  Solved: 1733

[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

为何狼羊与最小割总是联系到一块?

因为它们总是要被分割开【分割开,割开,开】

把矩阵每个单元看做一个点,向四周单元引一条容量为1的边【每建一个围栏代价为1】

如果属于羊,由S引一条容量为INF的边

如果属于狼,向T引一条容量为INF的边

这样最小割的边一定不是S和T相关的,而狼属于T,羊属于S,最小割算法就可以用最小的代价把它们分割开

其实想到最小割就很容易想到了

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
using namespace std;
const int maxn = 10005,maxm = 100005,maxv = 105,INF = 1000000000;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
int n,m,S,T,d[maxn],X[4] = {0,0,-1,1},Y[4] = {1,-1,0,0},q[maxn],cur[maxn];
bool vis[maxn];
int head[maxn],nedge = 0;
struct EDGE{int to,f,next;}edge[maxm];
inline void build(int u,int v,int w){
edge[nedge] = (EDGE){v,w,head[u]}; head[u] = nedge++;
edge[nedge] = (EDGE){u,0,head[v]}; head[v] = nedge++;
}
bool bfs(){
for (int i = 0; i <= T; i++) vis[i] = false;
int u,h = 0,t = 0,to;
d[S] = 0; vis[S] = true; q[++t] = S;
while (h < t){
u = q[++h];
Redge(u) if (edge[k].f && !vis[to = edge[k].to]){
d[to] = d[u] + 1; vis[to] = true; q[++t] = to;
}
}
return vis[T];
}
int dfs(int u,int minf){
if (u == T || !minf) return minf;
int flow = 0,f,to;
if (cur[u] == -2) cur[u] = head[u];
for (int& k = cur[u]; k != -1; k = edge[k].next)
if (d[to = edge[k].to] == d[u] + 1 && (f = dfs(to,min(minf,edge[k].f)))){
edge[k].f -= f;
edge[k ^ 1].f += f;
flow += f;
minf -= f;
if (!minf) break;
}
return flow;
}
int maxflow(){
int flow = 0;
while (bfs()){
fill(cur,cur + maxn,-2);
flow += dfs(S,INF);
}
return flow;
}
inline int id(int x,int y){return m * (x - 1) + y;}
int main(){
memset(head,-1,sizeof(head));
n = RD(); m = RD(); S = 0; T = n * m + 1; int u,x,y;
REP(i,n) REP(j,m){
u = id(i,j);
for (int k = 0; k < 4; k++){
x = i + X[k]; y = j + Y[k];
if (x && y && x <= n && y <= m) build(u,id(x,y),1);
}
x = RD();
if (x == 1) build(S,u,INF);
else if (x == 2) build(u,T,INF);
}
cout<<maxflow()<<endl;
return 0;
}

BZOJ1412 [ZJOI2009]狼和羊的故事 【最小割】的更多相关文章

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

    题目描述 “狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈 ...

  2. 【BZOJ1412】[ZJOI2009]狼和羊的故事 最小割

    [BZOJ1412][ZJOI2009]狼和羊的故事 Description “狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想: ...

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

    显然是最小割...把狼的领地连S, 羊的领地连T, 然后中间再连边, 跑最大流就OK了 -------------------------------------------------------- ...

  4. P2598 [ZJOI2009]狼和羊的故事(最小割)

    P2598 [ZJOI2009]狼和羊的故事 说真的,要多练练网络流的题了,这么简单的网络流就看不出来... 题目要求我们要求将狼和羊分开,也就是最小割,(等等什么逻辑...头大....) 我们这样想 ...

  5. [ZJOI2009] 狼与羊的故事 - 最小割

    给定一个\(N \times M\)方格矩阵,每个格子可在\(0,1,2\)中取值.要求在方格的边上进行划分,使得任意联通块内不同时包含\(1\)和\(2\)的格子. ________________ ...

  6. BZOJ1412 ZJOI2009 狼和羊的故事 【网络流-最小割】

    BZOJ1412 ZJOI2009 狼和羊的故事 Description “狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和 ...

  7. bzoj1412: [ZJOI2009]狼和羊的故事

    空地之间开始没有连然后一直WA...题意混乱...尴尬. #include<cstdio> #include<cstring> #include<iostream> ...

  8. LG2598/BZOJ1412 「ZJOI2009」狼和羊的故事 最小割

    问题描述 LG2598 BZOJ1412 题解 看到要把狼和羊两个物种分开 自然想到最小割. 发现\((x,y)\)可以向上下左右走以获得贡献,所以建边:\((x,y),(x-1,y)\),\((x, ...

  9. bzoj1412: [ZJOI2009]狼和羊的故事(最小割)

    传送门 首先,考虑只有狼和羊怎么办.我们把源点向所有羊连边,容$inf$,所有狼向汇点连边,容$inf$,然后羊向周围所有的狼连边,容$1$.那么,只要求一个割就能把狼和羊给分开,求一个最小割就是答案 ...

随机推荐

  1. WEB安全基础之sql注入基础

    1.基础sql语句 注释 单行注释# %23--+ --加空格多行注释/**/ SELECT(VERSION()) SELECT(USER()) SELECT(database()) 查数据库 SEL ...

  2. 用最简单的MVC模式输出内容

    MVC是模型(model)-视图(view)-控制器(controller)的缩写,它的作用是使代码分离,可维护性高.重用性高 编写Model层: <?php class model{ publ ...

  3. 第三十九篇 Python异常处理

    一. 什么是异常 异常就是程序运行时发生的错误,在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止,在python中,错误触发的异常如下 错误分成两种: #语法 ...

  4. 一种跨平台的C++遍历目录的方法

    参考了网络上各路大神的实现方法.主要使用了io.h库 #include <iostream> #include <cstring> #include <io.h> ...

  5. Sharepoint 2013与Sharepoint 2016的功能对比

    开发人员功能 SharePoint Foundation 2013 SharePoint Server 2013 Standard CAL SharePoint Server 2013 Enterpr ...

  6. 【模板】DFS

    int dx[] = { 0,1,0,-1 }; int dy[] = { 1,0,-1,0 }; void dfs()//参数用来表示状态 { if (到达终点状态) { ...//根据题意来添加 ...

  7. Linux下安装paramiko

    paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 由于使用的是python这样的能够跨平台运行的语言,所以所有python支持的平台, ...

  8. JS中Text节点总结

    文本节点有Text类型表示,包含的是可以找字面解释的纯文本内容.纯文本中可以包含转移后的HTML字符,但不能包含HTML代码.Text节点具有以下属性: 1.nodeType的值为3. 2.nodeN ...

  9. JavaScript中childNodes和children的区别

    我在学习JavaScript对DOM操作的过程中,发现了使用childNodes属性,得不到我想要的结果,因此我就从JavaScript高级程序设计中了解了childNodes和children的区别 ...

  10. Thunder团队第三周 - Scrum会议1

    Scrum会议1 小组名称:Thunder 项目名称:i阅app Scrum Master:王航 工作照片: 杨梓瑞在拍照,所以不在照片中. 参会成员: 王航(Master):http://www.c ...