题目描述

在游戏中,JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻击。两种攻击方式都会消耗JYY一些体力。采用普通攻击进攻怪兽并不能把怪兽彻底杀死,怪兽的尸体可以变出其他一些新的怪兽,注意一个怪兽可能经过若干次普通攻击后变回一个或更多同样的怪兽;而采用法术攻击则可以彻底将一个怪兽杀死。

游戏世界中一共有N种不同的怪兽,分别由1到N编号,现在1号怪兽入侵村庄了,JYY想知道,最少花费多少体力值才能将所有村庄中的怪兽全部杀死呢?

输入

第一行包含一个整数N。

接下来N行,每行描述一个怪兽的信息;

其中第i行包含若干个整数,前三个整数为Si,Ki和Ri,表示对于i号怪兽,普通攻击需要消耗Si的体力,法术攻击需要消耗Ki的体力。同时i号怪兽死亡后会产生Ri个新的怪兽。表示一个新出现的怪兽编号。同一编号的怪兽可以出现多个。

输出

输出一行一个整数,表示最少花费的体力值。

输入样例

4
4 27 3 2 3 2
3 5 1 2
1 13 2 4 2
5 6 1 2

输出样例

26

提示

样例解释

首先用花费4点体力用普通攻击,然后出现的怪兽编号是2,2和3。再花费10点体力用法术攻击杀死两个编号为2的怪兽。剩下3号怪兽,花费1点体力用普通攻击。此时村庄里还有编号为2和4的怪兽。最后花费11点体力用法术攻击将这两只怪兽彻底杀死。一共花费的体力是\(4+5+5+1+5+6=26\)。

数据规模

\(2≤N≤2×10^5 ,1≤R_i,ΣR_i≤10^6 ,1≤K_i,S_i≤5×10^{14}\)

主要思路

定义\(f_i\)表示完全清除第i个怪兽的体力。

不难得出 \(f_i=min(k_i,s_i+\underset{j表示i怪兽死亡后产生的新怪兽}{Σf_j})\)

而这个生成的怪兽链可能形成个环,所以我们不能用传统DP的方法做。而要使用spfa跑这个\(f_i\)。

首先需要建一张图 \(G1\) ,\(i\)死后生成了\(j\)就可以连一条\(i->j\)的边

然后需要建一张反图,用来\(f_i\)更新时,让\(f_i\)的父节点入队更新。

更新条件是\(s_i+Σf_j<f_i\)。

不难看出\(f_i\)的不可能大于\(k_i\),所以可以用\(k_i\)为\(f_i\)初始化。

代码

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std; typedef long long ll; const int N = 2e5 + 128;
const int M = 1e6 + 128; struct ios//快读
{
inline char read()
{
static const int IN_LEN = 1 << 18 | 1;
static char buf[IN_LEN], *s, *t;
return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
} template <typename _Tp>
inline ios &operator>>(_Tp &x)
{
static char c11, boo;
for (c11 = read(), boo = 0; !isdigit(c11); c11 = read())
{
if (c11 == -1)
return *this;
boo |= c11 == '-';
}
for (x = 0; isdigit(c11); c11 = read())
x = x * 10 + (c11 ^ '0');
boo && (x = -x);
return *this;
}
} io; namespace G1
{
int head[N], nxt[M], to[M];
int p = 0; inline void add_edge(int f, int t)
{
to[++p] = t;
nxt[p] = head[f];
head[f] = p;
}
} namespace G2 //反图
{
int head[N], nxt[M], to[M];
int p = 0; inline void add_edge(int f, int t)
{
to[++p] = t;
nxt[p] = head[f];
head[f] = p;
}
} ll s[N], k[N]; ll f[N]; bool vis[N]; int n; ll spfa()
{
queue<int> Q;
for (int i = 1; i <= n; i++)
Q.push(i);
while (!Q.empty())
{
int k = Q.front();
Q.pop();
vis[k] = false; ll sum = s[k];
for (int i = G1::head[k]; i != 0; i = G1::nxt[i])
sum += f[G1::to[i]];
if (sum < f[k])
{
f[k] = sum;
for (int i = G2::head[k]; i != 0; i = G2::nxt[i])//通知父节点
if (!vis[G2::to[i]])
Q.push(G2::to[i]), vis[G2::to[i]] = true;
;
}
}
return f[1];
} int main()
{
io >> n;
for (int i = 1; i <= n; i++)
{
int r;
io >> s[i] >> k[i] >> r;
for (int j = 1; j <= r; j++)
{
int t;
io >> t;
G1::add_edge(i, t);
G2::add_edge(t, i);
}
f[i] = k[i];
}
printf("%lld", spfa());
return 0;
}

[AHOI2014/JSOI2014/一本通1722]骑士游戏 题解 (spfa做dp)的更多相关文章

  1. 2019.01.22 bzoj3875: [Ahoi2014&Jsoi2014]骑士游戏(spfa+dp)

    传送门 题意简述:nnn个怪物,对于编号为iii的怪物可以选择用aia_iai​代价将其分裂成另外的bib_ibi​个怪物或者用cic_ici​代价直接消灭它,现在问消灭编号为1的怪物用的最小代价. ...

  2. 「AHOI2014/JSOI2014」骑士游戏

    「AHOI2014/JSOI2014」骑士游戏 传送门 考虑 \(\text{DP}\). 设 \(dp_i\) 表示灭种(雾)一只编号为 \(i\) 的怪物的代价. 那么转移显然是: \[dp_i ...

  3. 【BZOJ3875】[Ahoi2014&Jsoi2014]骑士游戏 SPFA优化DP

    [BZOJ3875][Ahoi2014&Jsoi2014]骑士游戏 Description  [故事背景] 长期的宅男生活中,JYY又挖掘出了一款RPG游戏.在这个游戏中JYY会扮演一个英勇的 ...

  4. BZOJ 3875: [Ahoi2014]骑士游戏 dp+spfa

    题目链接: 题目 3875: [Ahoi2014]骑士游戏 Time Limit: 30 Sec Memory Limit: 256 MB 问题描述 [故事背景] 长期的宅男生活中,JYY又挖掘出了一 ...

  5. BZOJ 3875: [Ahoi2014]骑士游戏 spfa dp

    3875: [Ahoi2014]骑士游戏 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=3875 Description [故事背景] 长 ...

  6. 【BZOJ3875】【AHOI2014】骑士游戏 [Spfa][DP]

    骑士游戏 Time Limit: 30 Sec  Memory Limit: 256 MB[Submit][Status][Discuss] Description 在这个游戏中,JYY一共有两种攻击 ...

  7. bzoj3875 【Ahoi2014】骑士游戏 spfa处理后效性动规

    骑士游戏 [故事背景] 长期的宅男生活中,JYY又挖掘出了一款RPG游戏.在这个游戏中JYY会 扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽. [问题描述] 在这个游戏中,JYY一共有两种攻 ...

  8. [bzoj3875] [Ahoi2014]骑士游戏

    3875: [Ahoi2014]骑士游戏 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 844  Solved: 440[Submit][Status ...

  9. BZOJ 3875: [Ahoi2014]骑士游戏

    d[i]表示消灭i所需的最小体力值, d[i] = min(S[i], K[i]+Σd[x]), Σd[x]表示普通攻击而产生的其他怪兽. 因为不是DAG, 所以用个队列类似SPFA来更新答案. -- ...

  10. bzoj 3875 骑士游戏 - spfa - 动态规划

    Description  [故事背景] 长期的宅男生活中,JYY又挖掘出了一款RPG游戏.在这个游戏中JYY会 扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽. [问题描述] 在这个游戏中,J ...

随机推荐

  1. Kotlin 协程二 —— 通道 Channel

    目录 一. Channel 基本使用 1.1 Channel 的概念 1.2 Channel 的简单使用 1.3 Channel 的迭代 1.4 close 关闭 Channel 1.5 Channe ...

  2. 【LeetCode二叉树#20】二叉搜索树转换为累加树,巩固二叉树的遍历(特殊的中序遍历)

    将二叉搜索树转换为累加树 力扣题目链接(opens new window) 给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 no ...

  3. 【Azure 环境】标准版 Logic App 如何查看 Workflow的执行成功数和失败数的指标呢?

    问题描述 在Azure中创建逻辑应用(Logic App),有两种计划类型.一是消费型,另一种是标准型. 在消费型的Logic App Metrics页面中,我们可以看见Workflow的执行成功数指 ...

  4. sort自定义排序字符串('1-1','2-1','3-2'此类)

    对数组排序 ['2-3','2-1','1-4','3-2','1-1','2-2','3-1'] 直接使用原生sort 对对象排序 [{a:'2-3'},{a:'2-1'},{a:'1-4'},{a ...

  5. AWS API Gateway IP WhileList

    首先创建个API,然后进入API配置,点击左边的资源配置,加入以下配置: { "Version": "2012-10-17", "Statement& ...

  6. dubbo 泛化调用场景下,如何调用下游的泛型对象入参

    dubbo泛化调用时,除了java原生的collection,map泛型对象,业务自定义的泛型对象是不支持泛化调用的,无法正确的填充下游数据对象.两种解法: 泛化调用的时候把泛型具体类型的全限定类路径 ...

  7. 常用命令rsyncscp-1

    常用命令:rsync/scp scp scp命令文件传输 scp命令用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能 ...

  8. [TM4] TM4C123G Keil5 新建工程指南

    [TM4] TM4C123G Keil5 新建工程指南 keil新建工程,选择TM4C123GH6PM芯片,然后在CMSIS勾选CORE,DEVICE勾选Startup(如图),来到新工程界面 在So ...

  9. 实时3D渲染它是如何工作的?可以在哪些行业应用?

    随着新兴技术--3D渲染的发展,交互应用的质量有了极大的提高.用实时三维渲染软件创建的沉浸式数字体验,几乎与现实没有区别了.随着技术的逐步改进,在价格较低的个人工作站上渲染3D图像变得更加容易,设计师 ...

  10. TagProvider 与 Enricher 丰富日志

    TagProvider  [LogProperties] 与 [LogPropertyIgnore] 如果用在DTO不存在任何问题,如果用在Domain实体上,可能有点混乱. 您可能不希望因日志记录问 ...