题目描述

在游戏中,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. iOS 面向对象与类

    至于未来会怎样,要走下去才知道反正路还很长,天总会亮. 1. 面向对象 1.1 什么是面向对象(OOP) 面向对象 Object Oriented Programming.在软件开发中,我们虽然用的是 ...

  2. 【LeetCode双指针】合并两个有序数组,从后向前遍历

    合并两个有序数组 https://leetcode.cn/problems/merge-sorted-array/ 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m ...

  3. 【LeetCode排序专题01】由旋转数组的最小数字引出的关于排序算法的讨论(冒泡排序、二分查找+暴力法)

    旋转数组的最小数字 剑指 Offer 11. 旋转数组的最小数字 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 给你一个可能存在 重复 元素值的数组 numbers ,它原来是一 ...

  4. ZYNQ SD卡 CDn管脚的作用

    ## 什么 是CDn? card detect, active low,用于指示当前SD卡是否插入,主机通过检测CD脚的状态来识别当前SD卡的状态. CD可以连接到MIO或者EMIO的任意空闲管脚,通 ...

  5. 适配http分发Directory.Build.props文件,需要替换默认的微软sdk:8.0映像

    背景 我们是把Directory.Build.props及其Import的文件,都放在http://dev.amihome.cn 那么docker build的时候,也是需要下载Directory.B ...

  6. 【Azure App Service】App Service设置访问限制后,使用git clone代码库出现403报错

    问题描述 在App Service中,为App Service配置了访问限制,结果导致在克隆App Service的代码时候,遇见403错误. 问题解答 因为在使用 git clone App Ser ...

  7. 调试 Docker 容器内部进程

    首发于官方博客:https://nebula-graph.com.cn/posts/debug-nebula-graph-processes-docker/ 摘要:本文以 Nebula Graph 进 ...

  8. BeanShell Sampler 前置处理器

    一概念: 前置处理器主要作用: 用于修改即将发送的http的请求数据 BeanShell预处理器可以在取样器发送请求之前被执行,可以通过它完成发送请求所需的数据 其中的ctx.vars.props.p ...

  9. XSS漏洞原理整理

    一.通常使用XSS脚本来获取浏览器版本信息,alert(navigator.userAgnet )  ,浏览器的UserAgent是可以伪造的,比方火狐或者很多扩展都可以屏蔽或者自定义浏览器发送的Us ...

  10. redis开启多端口

    Centos安装多端口的redis服务 背景 redis默认端口6379,由于开发需要,key有重复.于是另起端口6380. 配置服务过程 1.新建/etc/redis6380.conf,内容如下: ...