【题目链接】
【思路要点】
- 考虑类似于用类似Dijkstra算法的贪心过程确定消灭每个怪兽的最小花费。
- 用一个堆维护当前的最小花费集合,每次找出堆顶元素,确定为最终最小花费,并用这个值更新其它相关的最小花费。
- 时间复杂度\(O(NLogN)\)。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 200005; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } struct info {long long val; int pos; }; int n; bool vis[MAXN]; vector <int> a[MAXN], b[MAXN]; long long va[MAXN], vb[MAXN], dist[MAXN]; bool operator < (info a, info b) {return a.val > b.val; } priority_queue <info> Heap; int main() { read(n); for (int i = 1; i <= n; i++) { read(va[i]), read(vb[i]); int k; read(k); while (k--) { int x; read(x); a[i].push_back(x); b[x].push_back(i); } } for (int i = 1; i <= n; i++) { dist[i] = vb[i]; for (unsigned j = 0; j < a[i].size(); j++) va[i] += vb[a[i][j]]; chkmin(dist[i], va[i]); Heap.push((info) {dist[i], i}); } while (!vis[1]) { info tmp = Heap.top(); Heap.pop(); if (vis[tmp.pos]) continue; vis[tmp.pos] = true; for (unsigned i = 0; i < b[tmp.pos].size(); i++) { int dest = b[tmp.pos][i]; va[dest] -= vb[tmp.pos] - tmp.val; if (va[dest] < dist[dest]) { dist[dest] = va[dest]; Heap.push((info) {dist[dest], dest}); } } } writeln(dist[1]); return 0; }