Description
给定一张有向图 点权(当然你也可以理解为边权)为d or z-d 求在哪个点权值最大并且输出权值 如果可以无限制增加权值就输出-1
Solution
因为无限制增加权值就是一个环 于是我们就想到了这样一种可以判断环的算法:
SPFA! 当然并不是纯粹的SPFA 我们可以用优先队列(小根堆)来进行优化
我们把点权看作边权 如果无需花费钱的话 边权为d 如果需要花费的话 边权为z-d 从起点s跑一边SPFA求单源最长路 最后取一个最大的就可以了
环怎样判断?
我们用一个数组times 来记录这个点被松弛了几次 根据原理 如果一个点被松弛了>=n次 就是出现了一个环
Code
1 #include <iostream>
2 #include <cstdio>
3 #include <queue>
4 #include <cstdlib>
5 using namespace std;
6 int d, p, c, f, s, num;
7 int head[1100], dis[1100], vis[1100], times[1100];
8 priority_queue<int, vector<int>, greater<int> >q;
9 struct emmm {
10 int next, to, dis;
11 }e[1100];
12 void add(int from, int to, int dis) {
13 e[++num].next = head[from];
14 e[num].to = to;
15 e[num].dis = dis;
16 head[from] = num;
17 }
18 void spfa(int s) {
19 q.push(s);
20 vis[s] = 1;
21 dis[s] = d;
22 times[s]++;
23 while (!q.empty()) {
24 int now = q.top();
25 q.pop();
26 vis[s] = 0;
27 for (int i = head[now];i; i = e[i].next) {
28 int v = e[i].to;
29 if (dis[v] < dis[now] + e[i].dis) {
30 dis[v] = dis[now] + e[i].dis;
31 if (!vis[v]) {
32 q.push(v);
33 vis[v] = 1;
34 times[v]++;
35 if (times[v] >= c) cout << -1 << endl, exit(0);
36 }
37 }
38 }
39 }
40 }
41 int main() {
42 ios::sync_with_stdio(false);
43 cin >> d >> p >> c >> f >> s;
44 int x, y, z;
45 for (int i = 1;i <= p; i++) {
46 cin >> x >> y;
47 add(x, y, d);
48 }
49 for (int i = 1;i <= f; i++) {
50 cin >> x >> y >> z;
51 add(x, y, d-z);
52 }
53 spfa(s);
54 int ans = 0;
55 for (int i = 1;i <= c; i++)
56 ans = max(ans, dis[i]);
57 cout << ans << endl;
58 return 0;
59 }