[AHOI2014/JSOI2014]骑士游戏

题目

思博贪心题写了一个半小时没救了,我也没看出这是一个\(spfa\)来啊

设\(dp_i\)表示彻底干掉第\(i\)只怪物的最小花费,一个非常显然的事情,就是对于\(k_i\)值最小的怪物满足\(dp_i=k_i\)

非常好理解,反正到最后都要干掉这个怪物,何必再把它干成别的怪物

于是我们按照\(k_i\)的值先排序一下,另外维护一个小根堆

如果堆里没有点或者堆顶的\(dp\)值比当前的\(k\)要大,我们直接令当前当前\(k_i\)值最小的点\(i\)的\(dp_i=k_i\),之后遍历所有能到达点\(i\)的点\(v\),令\(s_v+=dp_i\),如果发现点\(v\)的所有出边都被遍历了一遍,我们就令\(dp_v=\min(s_v,k_v)\),同时把这个点加入堆中

如果堆里有点且堆顶的\(dp\)小于于当前\(k\),就直接拿堆顶来更新

考虑这个做法的正确性,显然当前堆中没有节点的时候,图中任意一个点不可能只分解成已经处理好\(dp_i\)的点,于是我们必须引入剩下的\(k\)值最小的点

或者把堆中没有点的情况视为初始情况,可能这样更好理解

代码

#include <bits/stdc++.h>
#define re register
#define LL long long
#define mp std::make_pair
#define min(a, b) ((a) < (b) ? (a) : (b))
const int maxn = 2e5 + 5;
struct E {
    int v, nxt;
} e[1000005];
LL dp[maxn], s[maxn], w[maxn];
int head[maxn], vis[maxn], c[maxn], p[maxn];
int n, num, top;
inline LL read() {
    LL x = 0;
    char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9') x = (x << 3ll) + (x << 1ll) + c - 48, c = getchar();
    return x;
}
typedef std::pair<LL, int> pii;
std::priority_queue<pii, std::vector<pii>, std::greater<pii> > q;
inline int cmp(int a, int b) { return s[a] < s[b]; }
inline void del(int x) {
    vis[x] = 1;
    for (re int i = head[x]; i; i = e[i].nxt) {
        if (vis[e[i].v])
            continue;
        w[e[i].v] += dp[x];
        c[e[i].v]--;
        if (!c[e[i].v])
            vis[e[i].v] = 1, dp[e[i].v] = min(w[e[i].v], s[e[i].v]), q.push(mp(dp[e[i].v], e[i].v));
    }
}
inline void add(int x, int y) {
    e[++num].v = y;
    e[num].nxt = head[x];
    head[x] = num;
}
int main() {
    n = read();
    for (re int x, i = 1; i <= n; i++) {
        w[i] = read(), s[i] = read(), c[i] = read();
        for (re int j = 1; j <= c[i]; j++) x = read(), add(x, i);
    }
    for (re int i = 1; i <= n; i++) p[i] = i;
    std::sort(p + 1, p + n + 1, cmp);
    int now = 1, tot = 0;
    while (tot < n) {
        while (vis[p[now]]) ++now;
        if (!q.empty() && (q.top().first < s[p[now]] || now > n))
            tot++, del(q.top().second), q.pop();
        else
            tot++, dp[p[now]] = s[p[now]], del(p[now++]);
    }
    printf("%lld\n", dp[1]);
    return 0;
}

原文地址:https://www.cnblogs.com/asuldb/p/11291426.html

时间: 2024-10-08 20:44:36

[AHOI2014/JSOI2014]骑士游戏的相关文章

BZOJ3875: [Ahoi2014&amp;Jsoi2014]骑士游戏

Description [故事背景] 长期的宅男生活中,JYY又挖掘出了一款RPG游戏.在这个游戏中JYY会 扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽. [问题描述] 在这个游戏中,JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻 击.两种攻击方式都会消耗JYY一些体力.采用普通攻击进攻怪兽并不能把怪兽彻底杀死,怪兽的尸体可以变出其他一些新的怪兽,注意一个怪兽可能经过若干次普通攻击后变回一个或更多同样的怪兽:而采用法术攻击则可以彻底将一个怪兽杀死.当然了,一般来说,相比普通攻

[AHOI2014/JSOI2014]骑士游戏(SPFA的本质)

题意 消灭一个魔物有两种方法,消耗\(a_i\)代价将它彻底消灭,或者消耗\(b_i\)代价将它变成多个其他魔物,求消灭1号魔物的最小代价 思路 SPFA:一个点的最短路径被更新后它的儿子节点才可能被更新,于是将该点入队,这样做减少了没有更新的无用枚举 对于这道题,设\(dis_i\)表示一个\(i\)魔物被彻底消灭的代价,(显然最多不超过\(a_i\)),类似上面的思路,不过这里将可能被更新的点入队(而不是上面的被更新过的点),取出队头的一个点,更新它的\(dis\)值,如果更新了就将所有可以

luogu P4042 [AHOI2014/JSOI2014]骑士游戏

这道题首先想到Dp.. 不妨设 f[i] 表示杀死怪兽 i 需要的最少体力, 那么有 f[i] = min( k[i] ,  s[i] + ∑ f [ri] ) , 这还是很好想的.. 但是没有办法转移啊,因为可能有环,高斯消元??,不存在的.. 然后就开始搞最短路了,但怎样建图呢,一般的跑最短路都是有起点,有终点,有边权,但这道题除了知道起点是 1 外,其他啥也没有.. 于是我们就需要深入理解SPFA的本质,所以说这是一道很好的思维题... SPFA是去不断的找最优解(松弛)..... 那么我

[AHOI2014/JSOI2014]骑士游戏(SPFA认识)

传送门 好题!考察了对于SPFA的深刻理解. 对于每个怪,我们要么花费魔攻代价,要么花费普攻代价+消灭其儿子的代价. 看似像个一直递归下去的做法,仿佛可以用dp? 但是图中可能会存在环,就会有后效性. 假如我们用一个队列保存当前还需要消灭的怪. 我们每次提出队首,要么魔攻,要么普攻然后又压入一堆新出现的怪.直到队为空. 感觉这个过程有点像SPFA. SPFA是对于每次那些还可能松弛更新的边进行松弛,直到无法操作(队空)就保证了最短路. 对于这道题,我们好像也可以每次看能不能再更新消灭怪的最小花费

【BZOJ3875】【Ahoi2014】骑士游戏 SPFA处理有后效性动规

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44040735"); } 题解: 首先一个点可以分裂成多个新点,这样就有了图上动规的基础. 即f[i]表示i点被消灭的最小代价,它可以由分裂出的点们更新. 但是这个东西有后效性,所以我们用SPFA来处理它. spfa处理后效性动规 我

「AHOI2014/JSOI2014」骑士游戏

「AHOI2014/JSOI2014」骑士游戏 传送门 考虑 \(\text{DP}\). 设 \(dp_i\) 表示灭种(雾)一只编号为 \(i\) 的怪物的代价. 那么转移显然是: \[dp_i = \min(K_i, S_i + \sum_{j = 1}^{R_i} dp_{v_j})\] 但是我们会发现这个东西是有后效性的... 所以我们会想要用建图然后跑一个最短路什么的来搞... 于是我们观察到上面那个 \(\text{DP}\) 式子中,\(dp_i\) 如果用后面那一项来转移,显然

BZOJ 3875 Ahoi2014 骑士游戏

3875: [Ahoi2014]骑士游戏 Time Limit: 30 Sec  Memory Limit: 256 MB Description [故事背景] 长期的宅男生活中,JYY又挖掘出了一款RPG游戏.在这个游戏中JYY会 扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽. [问题描述] 在这个游戏中,JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻击.两种攻击方式都会消耗JYY一些体力.采用普通攻击进攻怪兽并不能把怪兽彻底杀死,怪兽的尸体可以变出其他一些新的怪兽,注意一个

bzoj3876 [Ahoi2014&amp;Jsoi2014]支线剧情

3876: [Ahoi2014&Jsoi2014]支线剧情 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2180  Solved: 1300[Submit][Status][Discuss] Description [故事背景] 宅男JYY非常喜欢玩RPG游戏,比如仙剑,轩辕剑等等.不过JYY喜欢的并不是战斗场景,而是类似电视剧一般的充满恩怨情仇的剧情.这些游戏往往 都有很多的支线剧情,现在JYY想花费最少的时间看完所有的支线剧情. [问题描述

[luogu] P4040 [AHOI2014/JSOI2014]宅男计划(贪心)

P4040 [AHOI2014/JSOI2014]宅男计划 题目背景 自从迷上了拼图,JYY就变成了个彻底的宅男.为了解决温饱问题,JYY不得不依靠叫外卖来维持生计. 题目描述 外卖店一共有N种食物,分别有1到N编号.第i种食物有固定的价钱Pi和保质期Si.第i种食物会在Si天后过期.JYY是不会吃过期食物的. 比如JYY如果今天点了一份保质期为1天的食物,那么JYY必须在今天或者明天把这个食物吃掉,否则这个食物就再也不能吃了.保质期可以为0天,这样这份食物就必须在购买当天吃掉. JYY现在有M