BZOJ 1565 Luogu P2805 [NOI2009]植物大战僵尸 (Tarjan判环、最小割)
我: “立个flag 14点之前调完这题”
洛谷AC时间: 2019-06-24 14:00:16
实力打脸。。。
网络流板子从来写不对系列
题目链接: (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=1565
(luogu) https://www.luogu.org/problemnew/show/P2805
题解: 长得就那么像个最大权闭合子图啊。。。
\(i\)攻击\(j\)相当于如果想吃掉\(i\)必须吃掉\(j\), 另外如果吃掉\(i\)必须吃掉\(i\)右侧的点,最大权闭合子图。
但是可能有环,注意环并非要么全吃要么全不吃而是全都不能吃,所以用Tarjan提前判一下环,在环里的点和\(T\)连\(+\inf\)表示不能吃
时间复杂度\(O(MaxFlow(nm,(nm)^2))\).
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 602;
const int M = 362400;
const int INF = 1e8;
namespace MaxFlow
{
struct Edge
{
int v,w,nxt,rev;
} e[(M<<1)+3];
int fe[N+3];
int te[N+3];
int dep[N+3];
int que[N+3];
int n,en;
void addedge(int u,int v,int w)
{
en++; e[en].v = v; e[en].w = w;
e[en].nxt = fe[u]; fe[u] = en; e[en].rev = en+1;
en++; e[en].v = u; e[en].w = 0;
e[en].nxt = fe[v]; fe[v] = en; e[en].rev = en-1;
}
bool bfs()
{
for(int i=1; i<=n; i++) dep[i] = 0;
int head = 1,tail = 1; que[tail] = 1; dep[1] = 1;
while(head<=tail)
{
int u = que[head]; head++;
for(int i=fe[u]; i; i=e[i].nxt)
{
if(dep[e[i].v]==0 && e[i].w>0)
{
dep[e[i].v] = dep[u]+1;
tail++; que[tail] = e[i].v;
}
}
}
return dep[2]!=0;
}
int dfs(int u,int cur)
{
if(u==2) {return cur;}
int rst = cur;
for(int i=te[u]; i; i=e[i].nxt)
{
if(dep[e[i].v]==dep[u]+1 && e[i].w>0 && rst>0)
{
int flow = dfs(e[i].v,min(rst,e[i].w));
if(flow>0)
{
e[i].w-=flow; e[e[i].rev].w += flow; rst-=flow;
if(e[i].w>0) {te[u] = i;}
if(rst==0) {return cur;}
}
}
}
if(cur==rst) {dep[u] = 0;}
return cur-rst;
}
int dinic(int _n)
{
n = _n;
int ret = 0;
while(bfs())
{
for(int i=1; i<=n; i++) te[i] = fe[i];
ret += dfs(1,INF);
}
return ret;
}
}
namespace Tarjan
{
struct Edge
{
int v,nxt;
} e[M+3];
int fe[N+3];
int dfn[N+3],low[N+3],stk[N+3];
bool instk[N+3];
bool inscc[N+3];
int n,en,cnt,tp;
void addedge(int u,int v)
{
en++; e[en].v = v;
e[en].nxt = fe[u]; fe[u] = en;
}
void dfs(int u)
{
cnt++; dfn[u] = low[u] = cnt; tp++; stk[tp] = u; instk[u] = true;
for(int i=fe[u]; i; i=e[i].nxt)
{
if(!dfn[e[i].v])
{
dfs(e[i].v);
low[u] = min(low[u],low[e[i].v]);
}
else if(instk[e[i].v])
{
low[u] = min(low[u],low[e[i].v]);
}
}
if(low[u]>=dfn[u])
{
if(stk[tp]!=u) {inscc[u] = true;}
while(stk[tp]!=u)
{
inscc[stk[tp]] = true;
instk[stk[tp]] = false;
stk[tp] = 0; tp--;
}
stk[tp] = 0; tp--; instk[u] = false;
}
}
void work(int _n)
{
n = _n;
for(int i=1; i<=n; i++)
{
if(!dfn[i]) {dfs(i);}
}
}
}
int n,m;
int getid(int x,int y) {return x*m+y+3;}
int main()
{
scanf("%d%d",&n,&m); int ans = 0;
for(int i=1; i<=n*m; i++)
{
int x; scanf("%d",&x);
if(x>0) {MaxFlow::addedge(1,i+2,x); ans += x;}
else if(x<0) {MaxFlow::addedge(i+2,2,-x);}
scanf("%d",&x);
while(x--)
{
int y,z; scanf("%d%d",&y,&z); int pos = getid(y,z);
MaxFlow::addedge(pos,i+2,INF);
Tarjan::addedge(pos-2,i);
}
if(i%m!=0)
{
MaxFlow::addedge(i+2,i+3,INF);
Tarjan::addedge(i,i+1);
}
}
Tarjan::work(n*m);
for(int i=1; i<=n*m; i++)
{
if(Tarjan::inscc[i])
{
MaxFlow::addedge(i+2,2,INF);
}
}
int tmp = MaxFlow::dinic(n*m+2);
ans -= tmp;
printf("%d\n",ans);
return 0;
}
BZOJ 1565 Luogu P2805 [NOI2009]植物大战僵尸 (Tarjan判环、最小割)的更多相关文章
- 洛谷2805 [NOI2009]植物大战僵尸 (拓扑排序+最小割)
坚决抵制长题面的题目! 首先观察到这个题目中,我们会发现,我们对于原图中的保护关系(一个点右边的点对于这个点也算是保护) 相当于一种依赖. 那么不难看出这个题实际上是一个最大权闭合子图模型. 我们直接 ...
- 【BZOJ 3232】圈地游戏 二分+SPFA判环/最小割经典模型
最小割经典模型指的是“一堆元素进行选取,对于某个元素的取舍有代价或价值,对于某些对元素,选取后会有额外代价或价值”的经典最小割模型,建立倒三角进行最小割.这个二分是显然的,一开始我也是想到了最小割的那 ...
- 洛谷 P2805 [NOI2009]植物大战僵尸 解题报告
P2805 [NOI2009] 植物大战僵尸 题目描述 Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plan ...
- BZOJ 1565 / P2805 [NOI2009]植物大战僵尸 (最大权闭合子图 最小割)
题意 自己看吧 BZOJ传送门 分析 - 这道题其实就是一些点,存在一些二元限制条件,即如果要选uuu则必须选vvv.求得到的权值最大是多少. 建一个图,如果选uuu必须选vvv,则uuu向vvv连边 ...
- P2805 [NOI2009]植物大战僵尸 + 最大权闭合子图 X 拓扑排序
传送门:https://www.luogu.org/problemnew/show/P2805 题意 有一个n * m的地图,你可以操纵僵尸从地图的右边向左边走,走的一些地方是有能量值的,有些地方会被 ...
- 洛谷$P2805\ [NOI2009]$植物大战僵尸 网络流
正解:网络流 解题报告: 传送门$QwQ$ 题面好长昂,,,我大概概括下$QwQ$?有个$n\cdot m$的网格,每个格子有一株植物,击溃一株植物$(x,y)$需要付出$S_{(x,y)}$的代价( ...
- BZOJ 2039 / Luogu P1791 [2009国家集训队]employ人员雇佣 (最小割)
题面 BZOJ传送门 Luogu传送门 分析 考虑如何最小割建图,因为这仍然是二元关系,我们可以通过解方程来确定怎么建图,具体参考论文 <<浅析一类最小割问题 湖南师大附中 彭天翼> ...
- P2805 [NOI2009]植物大战僵尸(最小割+拓扑排序)
题意: n*m的矩阵,每个位置都有一个植物.每个植物都有一个价值(可以为负),以及一些它可以攻击的位置.从每行的最右面开始放置僵尸,僵尸从右往左行动,当僵尸在植物攻击范围内时会立刻死亡.僵尸每到一个位 ...
- P2805 [NOI2009]植物大战僵尸 (拓扑排序 + 最小割)
题意:N*M的矩阵 每个点上都有一颗植物 僵尸只能从每一行的最右边向左进攻 每个植物有攻击范围 可以保护在攻击范围内的植物 同时每一颗植物也保护他左边的植物 摧毁每个植物能获得价值 如果这个植物被保护 ...
随机推荐
- 爬虫—Selenium使用
Selenium使用 Selenium是一个自动化测试工具,可以驱动浏览器器执行特定的动作,如点击,下拉等.同时还可以获取浏览器当前呈现页面的源代码,可见即可爬. 1.准备 我们使用谷歌Chrome浏 ...
- C# 相关概念
解决方案 在磁盘上由 .sln 文件表示,是一个或多个相关项目的容器. 例如,如果为 Python 应用程序编写 C++ 扩展,该 C++ 项目可以驻留在同一解决方案中. 解决方案还可以包含 Web ...
- Hbase源码分析:server端RPC
server端rpc包括master和RegionServer.接下来主要梳理一下,master和regionserver中有关rpc创建,启动以及处理的过程. 1,server rpc的初始化过程 ...
- [译]The multi Interface
The multi Interfacemulti接口 The easy interface as described in detail in this document is a synchrono ...
- jquery.autocomplete.js用法及示例,小白进
8 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 ...
- javascript学习之Date对象
前几天学习了一下date对象,于是写了一个简单的时间显示放到博客页面里(位于右上角),类似这样的效果,时:分:秒 xxxx年xx月xx日. 下面来说一下具体实现步骤. 首先,既然date是一个对象,那 ...
- AngularJs与Java Web服务器交互
AngularJs是Google工程师研发的产品,它的强大之处不是几句话就能描述的,只有真正使用过的人才能体会到,笔者准备在这篇文章中,以一个简单的登录校验的例子说明如何使用AngularJs和Web ...
- Python学习日记之读取中文目录
unicode # -*- coding:utf-8 -*- import os import shutil ins="E:\\学习资料" dir=unicode(ins,'utf ...
- 阿里云机器学习tensorflow实践
1,前言 伴随人工智能和深度学习的应用越来越普及,越来越多的开发人员开始投入到智能算法的编程中.由于算法成熟且公开,软件编码这一块不存在难度:但模型训练和预测所需的时间与硬件设备的配置有极大关系,很多 ...
- js中原型和原型链
1.原型: 在JavaScript 中,对象被表现为prototype . 原型其实一直存在于我们接触过的任何一个对象. 2. Tip:在函数对象中也存在__proto__属性,但是查看函数对象的原型 ...