LuoGuP4042:[AHOI2014/JSOI2014]骑士游戏

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))的。

原文地址:https://www.cnblogs.com/ChiTongZ/p/11191246.html