Pre
真正的勇士,敢于面对爆零的悲惨。———沃兹基硕德
被虐了。
Solution
之前看过类似的(SPFA)总结,里面有提过解决这一类题的方法,但是没有做过题。今天碰巧遇上,就做了,也方便把算法记录在这里。
不停找更加优的可能性就可以了。
好像(SPFA)还有各种优化,但我懒得加,就直接交了。
Code
#include<bits/stdc++.h>
#ifdef wll
#include<windows.h>
#endif
#define xx first
#define yy second
#define ll long long
#define ull unsigned long long
using namespace std;
const int N = 200000 + 5, M = 1000000 + 5;
struct Graph {
int fr[M << 1], to[M << 1], h[N], tot;
inline void add (int u, int v) {
tot++;
fr[tot] = h[u];
to[tot] = v;
h[u] = tot;
}
}pos, neg;
ll s[N], dp[N], sum;
int n, r[N];
bool inq[N];
queue<int> Q;
inline void work () {
for (int i = 1; i <= n; ++i) {
Q.push (i);
inq[i] = 1;
}
while (Q.size ()) {
int u = Q.front ();
Q.pop ();
inq[u] = 0;
sum = s[u];
for (int i = pos.h[u]; i; i = pos.fr[i]) {
sum += dp[pos.to[i]];
}
if (sum < dp[u]) {
dp[u] = sum;
for (int i = neg.h[u]; i; i = neg.fr[i]) {
if (!inq[neg.to[i]]) {
Q.push (neg.to[i]);
inq[neg.to[i]] = 1;
}
}
}
}
printf ("%lld
", dp[1]);
}
int main () {
scanf ("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf ("%lld%lld%d", &s[i], &dp[i], &r[i]);
for (int j = 1; j <= r[i]; ++j) {
int tmp;
scanf ("%d", &tmp);
pos.add (i, tmp);
neg.add (tmp, i);
}
}
work ();
return 0;
}
Conclusion
(SPFA)时间复杂度永远是(O()玄学())
相信可以过(O(n logn))的。