[AHOI2014 / JSOI2014]ナイトゲーム

タイトル

貪欲SoftBrandsは、私はこれがあることを見ていなかった、絶望的な半分の時間を書いた\(spfa \)ああへ

セット\(dp_i \)は完全に取り除く最初表し\(私は\)モンスターの最小コストは、非常に明白なことは、のためである(K_I \)\最小モンスターの値応える\(dp_i = K_I \)

理解することは非常に簡単、とにかく、最後にこのモンスターを取り除くために必要があり、なぜその後、別のモンスターにそれを乾燥

だから我々は従う\(K_I \)小さなヒープルートを維持するだけでなく、それを注文する前に値を

スタックのないパイルポイントやトップが存在しない場合は、\(DP \)現在よりも値\は(K \)大きくなければならない、我々は聞かせて、現在の直流\(K_I \)極小点の値は\(I \) A \(dp_i = K_I \)その後、全ての点に到達横断\(Iは\)ポイント\(V \) そう\(S_Vは+ = dp_i \)見つかった点と、\(Vの\)縁の全てには、再び横断し、我々はそれになります\(dp_v = \分(S_Vは、Kvをある)\)をヒープのほかしばらくこの時点、

ヒープとの小さな山の頂上場合は\(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;
}

おすすめ

転載: www.cnblogs.com/asuldb/p/11291426.html