[洛谷P1938] 找工就业Job Hunt

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 }
AC Code

猜你喜欢

转载自www.cnblogs.com/-sheldon/p/11369702.html