题目大意:
设杀死怪物 $i$ 的最小代价为 $f[i]$,有
$j$ 为 $i$ 被普通攻击后分裂出的怪物。
考虑 $k_i$ 最小的点,这个怪兽肯定是被法术杀死的,它的 $f$ 值是确定的,于是只能变成这个怪兽的怪兽就可以转移了。这就很像拓扑序时的操作,每次选一个 $k_i$ 最小的点,更新 $f$ 值,如果某个点能变成所有的怪兽都被更新过了,那就更新这个怪兽,否则再重复这个过程直到所有怪兽都被更新完。
#include <cstdio>
#include <queue>
typedef long long LL;
const int N = 200005, M = 1000005;
struct Pair {
LL x; int y;
bool operator < (const Pair &rhs) const {
return x > rhs.x;
}
};
int vis[N], d[N], head[N], nxt[M], v[M], tot, n; LL k[N], s[N], t[N];
std::priority_queue<Pair> Q;
LL read() {
LL x = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') {
x = (x << 3) + (x << 1) + (c ^ 48);
c = getchar();
}
return x;
}
void adde(int from, int to) {
nxt[++tot] = head[from];
head[from] = tot, v[tot] = to;
}
void dijkstra() {
while (!Q.empty()) {
int u = Q.top().y; Q.pop();
if (vis[u]) continue;
if (u == 1) return;
vis[u] = 1;
for (int i = head[u]; i; i = nxt[i]) {
t[v[i]] += k[u];
if (--d[v[i]] == 0) {
if (k[v[i]] > t[v[i]] + s[v[i]])
k[v[i]] = t[v[i]] + s[v[i]];
Q.push((Pair){k[v[i]], v[i]});
}
}
}
}
int main() {
n = read();
for (int i = 1; i <= n; ++i) {
s[i] = read(), k[i] = read(), d[i] = read();
for (int j = 1; j <= d[i]; ++j) adde(read(), i);
Q.push((Pair){k[i], i});
}
dijkstra();
printf("%lld\n", k[1]);
return 0;
}