题目大意

有一个 (n times m) 的网格,每一个格子上是羊、狼、空地中的一种,羊和狼可以走上空地。现要在格子边上建立围栏,求把狼羊分离的最少围栏数。

(1 leqslant n, ; m leqslant 100)

题目链接

BZOJ 1412

CodeVS 2351

题解

最小割。

从源点向羊/狼连一条容量无限的边,从狼/羊向汇点连一条容量无限的边。考虑相邻的两格,若是一狼一羊,则连一条容量为 (1) 的边(分割狼羊),若至少有一方为空地,也连一条容量为 (1) 的边(狼羊会走上空地)。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <climits>
#include <queue>
#include <algorithm>
const int MAXN = 105;
struct ;
struct Node {
Edge *e, *curr;
int level;
} N[MAXN * MAXN];
struct {
Node *u, *v;
Edge *next, *rev;
int cap, flow;
Edge(Node *u, Node *v, int cap) : u(u), v(v), cap(cap), flow(0), next(u->e) {}
};
void addEdge(int u, int v, int cap) {
N[u].e = new Edge(&N[u], &N[v], cap);
N[v].e = new Edge(&N[v], &N[u], 0);
N[u].e->rev = N[v].e;
N[v].e->rev = N[u].e;
}
struct Dinic {
bool makeLevelGraph(Node *s, Node *t, int n) {
for (int i = 0; i < n; i++) N[i].level = 0;
std::queue<Node *> q;
q.push(s);
s->level = 1;
while (!q.empty()) {
Node *u = q.front();
q.pop();
for (Edge *e = u->e; e; e = e->next) {
大专栏  [BZOJ 1412][ZJOI 2009] 狼和羊的故事 if (e->cap > e->flow && e->v->level == 0) {
e->v->level = u->level + 1;
if (e->v == t) return true;
q.push(e->v);
}
}
}
return false;
}
int findPath(Node *s, Node *t, int limit = INT_MAX) {
if (s == t) return limit;
for (Edge *&e = s->curr; e; e = e->next) {
if (e->cap > e->flow && e->v->level == s->level + 1) {
int flow = findPath(e->v, t, std::min(limit, e->cap - e->flow));
if (flow > 0) {
e->flow += flow;
e->rev->flow -= flow;
return flow;
}
}
}
return 0;
}
int operator()(int s, int t, int n) {
int res = 0;
while (makeLevelGraph(&N[s], &N[t], n)) {
for (int i = 0; i < n; i++) N[i].curr = N[i].e;
int flow;
while ((flow = findPath(&N[s], &N[t])) > 0) res += flow;
}
return res;
}
} dinic;
int n, m;
int getID(int x, int y) {
return (x - 1) * m + y;
}
bool valid(int x, int y) {
return (x > 0) && (y > 0) && (x <= n) && (y <= m);
}
int main() {
scanf("%d %d", &n, &m);
const int s = 0, t = n * m + 1;
static int mat[MAXN][MAXN];
for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) {
scanf("%d", &mat[i][j]);
if (mat[i][j] == 2) addEdge(s, getID(i, j), INT_MAX);
if (mat[i][j] == 1) addEdge(getID(i, j), t, INT_MAX);
}
static int d[4][2] = {
{0, 1},
{0, -1},
{1, 0},
{-1, 0}
};
for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) {
for (int k = 0; k < 4; k++) {
int x = i + d[k][0], y = j + d[k][1];
if (!valid(x, y)) continue;
if (mat[i][j] != mat[x][y] || (mat[i][j] == mat[x][y] && mat[x][y] == 0))
addEdge(getID(i, j), getID(x, y), 1);
}
}
printf("%dn", dinic(s, t, t + 1));
return 0;
}

[BZOJ 1412][ZJOI 2009] 狼和羊的故事的更多相关文章

  1. 【BZOJ 1412】[ZJOI2009]狼和羊的故事

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

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

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

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

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

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

    1412: [ZJOI2009]狼和羊的故事 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3454  Solved: 1733 [Submit][ ...

  5. 【BZOJ1412】狼和羊的故事(网络流)

    [BZOJ1412]狼和羊的故事(网络流) 题面 Description "狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......" Orez听 ...

  6. P2598 [ZJOI2009]狼和羊的故事(网络流)

    P2598 [ZJOI2009]狼和羊的故事 源点和所有狼连 $inf$ 的边 所有羊和汇点连 $inf$ 的边 所有点向四周连 $1$ 的边 这样所有狼和羊之间的边都被割掉了 统计最小割就好辣 #i ...

  7. 洛谷 P2598 [ZJOI2009]狼和羊的故事 解题报告

    P2598 [ZJOI2009]狼和羊的故事 题目描述 "狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......" \(Orez\)听到这首歌, ...

  8. 题解 P2598 【[ZJOI2009]狼和羊的故事】

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

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

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

随机推荐

  1. sql字符串常用函数

    1.replace  REPLACE(String,from_str,to_str) 即:将String中所有出现的from_str替换为to_str 2.left  left(String,2) 从 ...

  2. 9. Dockerfile 实际操作 (把 python app 打包成 image 并运行)

    1. 创建并进入 flask-hello-world mkdir flask-hello-world && cd flask-hello-world 2. 编写 python 文件 a ...

  3. 18)C++对C的增强

    在C++中所有的变量都必须有类型,但是在C语言中没有这个要求,C语言中的默认类型在C++中不合法, #include<stdio.h> f() { ; } int main() { int ...

  4. Linux centos 常用的命令

    Linux centos 下载命令:wget Linux centos 访问命令:vi Linux centos 插入命令:i Linux centos 保存退出: :wq Linux centos  ...

  5. ios AVPlayer参考

    http://www.cnblogs.com/kenshincui/p/4186022.html#avPlayer

  6. mqtt协议系统设计参考

    作者:极寒链接:https://zhuanlan.zhihu.com/p/28525517来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 回顾自己的工作经历最遗憾的是没 ...

  7. USB Reverse Tether (a dirty solution)

    Tether your android phone to your PC using USB cable could share your 3g Internet connection with PC ...

  8. Hibernate实现分页查询

    分页查询就是把数据库中某张表的记录数进行分页查询,在做分页查询时会有一个Page类,下面是一个Page类,我对其做了详细的注解: 1 package com.entity; 2 /** 3 * @au ...

  9. 43)PHP,mysql_fetch_row 和mysql_fetch_assoc和mysql_fetch_array

    mysql_fetch_row   提取的结果是没有查询中的字段名了(也就是没有键id,GoodsName,只有值),如下图: mysql_fetch_assoc 提取的结果有键值,如下图: mysq ...

  10. LightGBM和XGBoost的区别?

    首先声明,LightGBM是针对大规模数据(样本量多,特征多)时,对XGBoost算法进行了一些优化,使得速度有大幅度提高,但由于优化方法得当,而精度没有减少很多或者变化不大,理论上还是一个以精度换速 ...