bzoj3875 [Ahoi2014]骑士游戏
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3875
【题解】
容易列出dp,但是是有后效性,我们用spfa来去除这种后效性即可,如果一个点可更新,把前面所有点加进来即可。
# include <queue> # include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 2e6 + 10, N = 5e5 + 10; const int mod = 1e9+7; # define RG register # define ST static int n; ll S[N]; int head[N], nxt[M], to[M], tot=0; inline void add(int u, int v) { ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; } int head2[N]; inline void add2(int u, int v) { ++tot; nxt[tot] = head2[u]; head2[u] = tot; to[tot] = v; } queue<int> q; ll d[M]; bool vis[M]; inline void spfa() { while(!q.empty()) q.pop(); for (int i=1; i<=n; ++i) q.push(i), vis[i] = 1; while(!q.empty()) { int top = q.front(); q.pop(); vis[top] = 0; ll a = S[top]; for (int i=head[top]; i; i=nxt[i]) a += d[to[i]]; if(a >= d[top]) continue; d[top] = a; for (int i=head2[top]; i; i=nxt[i]) if(!vis[to[i]]) q.push(to[i]), vis[to[i]] = 1; } } int main() { cin >> n; for (int i=1, t, tt; i<=n; ++i) { scanf("%lld%lld%d", &S[i], &d[i], &t); while(t--) { scanf("%d", &tt); add(i, tt); add2(tt, i); } } spfa(); cout << d[1]; return 0; }