[luogu2172] 部落战争
题面
我们可以将'.'抽象为一个可以通过的点, 将'x'抽象为一个不可通过的点.
那么题意便可以转化为: 一条路径可以看做从任意一个没有到达过的可通过的点出发到任意一个其他的可以通过却没有被到达过的点的一条路径, 要使每个点都被经过, 并且每个点都只能被经过一次, 这不是网络流中的最小路径覆盖吗, 大家可以去看一下魔术球问题, 魔术球问题就是最小路径覆盖的板子题.
对于这种题目, 我们将图中的每一个点拆为两个点<i, a>, <i, b>, 从源点向<i, a>连边, 从<i, b>向汇点连边, 若可从点\(i\)到达点\(j\), 就从点<i, a>向点<j, b>连一条边, 由于每个点都只能出现一次, 所以这些边的容量都是1, 然后跑一遍最大流即可, 这里还要注意一下的是, 军队只能向下走, 所以八个方向变为了四个方向, 分别是(c, r), (c, -r), (r, c), (r, -c).
跑完了最大流之后, 答案怎样统计呢, 我们最初每个可通过的点都是一条边, 所以最初有'.'的点数这么多条边, 我们不妨设这个数为\(sum\), 那么每次从点\(i\)向点\(j\)连边, 其实就意味着将两点之间的路径合并, 那么就会减少一条边, 我们又知道一个定理:最小点(在这个题中是路径(覆盖 = 点数 - 最大独立集 = 点数 - 最小割 = 点数 - 最大流, 所以最后的答案便是\(sum\) - \(dinic()\)的值, \(dinic()\)是一个函数, 他返回的是最大流的流量.
接下来还是看代码吧, 感觉解析应该没什么人会看...
具体代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define INF 1e9
using namespace std;
int m, n, R, C, mapp[105][105], u[4], v[4], S, T, head[100005], cnt = 1, cur[100005], d[100005], vis[100005], ans, sum;
struct node
{
int to, flow, next;
} edge[1000005];
inline int read()
{
int x = 0, w = 1;
char c = getchar();
while(c < '0' || c > '9') { if (c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
return x * w;
}
inline void add(int u, int v, int w)
{
edge[++cnt] = { v, w, head[u] }; head[u] = cnt;
edge[++cnt] = { u, 0, head[v] }; head[v] = cnt;
}
bool bfs()
{
memset(d, 0, sizeof(d)); d[S] = 1;
queue<int> q; q.push(S);
while(!q.empty())
{
int u = q.front(); q.pop();
for(int i = head[u]; i; i = edge[i].next)
{
int v = edge[i].to;
if(!d[v] && edge[i].flow > 0) { d[v] = d[u] + 1; q.push(v); }
}
}
return d[T];
}
int dfs(int u, int a)
{
if(u == T || !a) return a;
int flow = 0;
for(int &i = cur[u]; i; i = edge[i].next)
{
int v = edge[i].to;
if(d[v] == d[u] + 1 && edge[i].flow > 0)
{
int f = dfs(v, min(a, edge[i].flow));
a -= f; flow += f; edge[i].flow -= f; edge[i ^ 1].flow += f;
}
if(!a) break;
}
if(a) d[u] = -1;
return flow;
}
int dinic()
{
int flow = 0;
while(bfs())
{
memcpy(cur, head, sizeof(head));
flow += dfs(S, INF);
}
return flow;
}
int main()
{
m = read(); n = read(); R = read(); C = read();
for(int i = 1; i <= m; i++)
for(int j = 1; j <= n; j++)
{
char c; cin>>c;
mapp[i][j] = (c == 'x');
if(mapp[i][j] == 1) sum++;
}
u[0] = C; u[1] = C; u[2] = R; u[3] = R; v[0] = R; v[1] = -R; v[2] = -C; v[3] = C;
S = 2 * m * n + 1; T = S + 1;
for(int i = 1; i <= m; i++)
for(int j = 1; j <= n; j++)
{
add(S, (i - 1) * n + j, 1);
add((i - 1) * n + j + m * n, T, 1);
if(!mapp[i][j])
for(int k = 0; k < 4; k++)
{
int x = i + u[k], y = j + v[k];
if(x >= 1 && x <= m && y >= 1 && y <= n && !mapp[x][y]) add((i - 1) * n + j, (x - 1) * n + y + m * n, 1);
}
}
printf("%d\n", m * n - sum - dinic());
return 0;
}
话说为啥我自己的博客二级标题总是显示不出来呢
[luogu2172] 部落战争的更多相关文章
- BZOJ2150: 部落战争
题解: 把每个点拆成入点和出点,因为必须经过一次且只能经过一次.所以在两个点之间连一条上界=下界=1的边. 然后再s到每个入点连边,每个出点向t连边,点与点之间... 求最小流就可以过了... (感觉 ...
- BZOJ 2150: 部落战争 最大流
2150: 部落战争 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php? ...
- BZOJ-2150部落战争(最小路径覆盖)
2150: 部落战争 Time Limit: 10 Sec Memory Limit: 259 MB Description lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国 ...
- 【BZOJ5317】[JSOI2018]部落战争(凸包,闵可夫斯基和)
[BZOJ5317][JSOI2018]部落战争(凸包,闵可夫斯基和) 题面 BZOJ 洛谷 题解 很明显我们只需要两个凸包\(A,B\). 假设询问给定的方向向量是\(v\). 那么现在就是判断\( ...
- 【洛谷】4304:[TJOI2013]攻击装置【最大点独立集】【二分图】2172: [国家集训队]部落战争【二分图/网络流】【最小路径覆盖】
P4304 [TJOI2013]攻击装置 题目描述 给定一个01矩阵,其中你可以在0的位置放置攻击装置. 每一个攻击装置(x,y)都可以按照“日”字攻击其周围的8个位置(x-1,y-2),(x-2,y ...
- 【BZOJ2150】部落战争 最小流
[BZOJ2150]部落战争 Description lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土. A国是一个M*N的矩阵,其中某些地方是城镇, ...
- [bzoj2150]部落战争_二分图最小路径覆盖
部落战争 bzoj-2150 题目大意:题目链接. 注释:略. 想法: 显然是最小路径覆盖,我们知道:二分图最小路径覆盖等于节点总数-最大匹配. 所以我们用匈牙利或者dinic跑出最大匹配,然后用总结 ...
- bzoj2150: 部落战争(匈牙利)
2150: 部落战争 题目:传送门 题解: 辣鸡数据..毁我AC率 先说做法,很容易就可以看出是二分图匹配的最小路径覆盖(可能是之前不久刚做过类似的题) 一开始还傻逼逼的去直接连边然后准备跑floyd ...
- P2172 [国家集训队]部落战争(最小路径覆盖)
P2172 [国家集训队]部落战争 每个点仅走一次:最小路径覆盖 套路地拆点,具体看代码中的$draw()$ 流量每增加1,意味着一支军队可以多走一格,代价减少1 最后答案即为总点数$-dinic() ...
随机推荐
- Java - LinkedList源码分析
java提高篇(二二)---LinkedList 一.概述 LinkedList与ArrayList一样实现List接口,只是ArrayList是List接口的大小可变数组的实现,LinkedList ...
- EF数据库优先模式(三)
今天2018年4月1日,呼叫王伟,81192,收到请返航! 接上次说,本节将LINQ以及lambda表达式 LINQ是C#里面针对SQL Server特有的数据访问操作方法,通俗一点说就是类似于写SQ ...
- 《Inside Solid State Device》读书笔记
这周我看了<Inside Solid State Device>一书,了解了解SSD作为软件的补充. 固态硬盘区别于将数据以磁形式存储的机械硬盘,使用了一种名为NAND的闪存颗粒,以电信号 ...
- Logback 日志持久化
Logback是log4j的增强版,比log4j更具灵活,其提供了将日志输出到数据库的功能,本文将介绍如何将指定的日志输出到mysql中. 一.自定义log标志 由于Logback原生的配置会将所有的 ...
- Python标准库--UUID
UUID(Universally Unique Identifier)是128位通用唯一识别码,通常由32字节的字符串表示.它可以保证时间和空间的唯一性,也称为GUID,全称为:UUID —— Uni ...
- git 本地安装
一.基本安装 1.下载Git 官方地址为:https://git-scm.com/download/win 2.下载完之后,双击安装,全部选择默认. 3.选择安装目录 4.选择组件 5.开始菜单目 ...
- 图片圆角显示与手机版文章页面CSS布局
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 转:PHPStorm+XDebug进行调试图文教程
原文:PHPStorm+XDebug进行调试图文教程 一.XDebug安装配置 (1)下载XDebug下载地址:http://www.xdebug.org/必须下载跟机器上安装的php匹配的版本才行. ...
- js柯里化
这篇文章讲的很好啊~例子很好 http://www.zhangxinxu.com/wordpress/2013/02/js-currying/ 这篇是讲函数式编程的,其中也有涉及到,说明了柯里化是一种 ...
- 如何选型商业智能和分析平台,Gartner给了这些建议!
文 | 水手 在2017年1月20日Gartner发布的<China Summary Translation: 'Survey Analysis: Customers Rate Their BI ...