POJ-1860.CurrencyExchange(Spfa判断负环模版题)

  本题思路:每完成一次交换之后交换余额多于原钱数则存在正环,输出YES即可。

参考代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <queue>
 5 using namespace std;
 6 
 7 const int maxn = 5e2;
 8 struct node {
 9     int to, next;
10     double r, c;
11 } G[maxn];
12 int n, m, s, num;
13 int head[maxn];
14 double v;
15 double dist[maxn];
16 bool vis[maxn];
17 
18 void addedge(int u, int v, double r, double c) {
19     G[++num].to = v;
20     G[num].r = r;
21     G[num].c = c;
22     G[num].next = head[u];
23     head[u] = num;
24 }
25 
26 bool Spfa(int s, double v) {
27     queue <int> Q;
28     Q.push(s);
29     dist[s] = v;
30     while(!Q.empty()) {
31         int now = Q.front();    Q.pop();
32         vis[now] = false;
33         for(int k = head[now]; k; k = G[k].next) {
34             int next = G[k].to;
35             if(dist[next] < (dist[now] - G[k].c) * G[k].r) {
36                 dist[next] = (dist[now] - G[k].c) * G[k].r;
37                 if(!vis[next]) {
38                     Q.push(next);
39                     vis[next] = true;
40                 }
41             }
42         }
43         if(dist[s] > v) return true;
44     }
45     return false;
46 }
47 
48 int main () {
49     scanf("%d %d %d %lf", &n, &m, &s, &v);
50     int a, b;
51     double r1, c1, r2, c2;
52     while(m --) {
53         scanf("%d %d %lf %lf %lf %lf", &a, &b, &r1, &c1, &r2, &c2);
54         addedge(a, b, r1, c1);
55         addedge(b, a, r2, c2);
56     }
57     if(Spfa(s, v))  printf("YES\n");
58     else    printf("NO\n");
59     return 0;
60 }
View Code

  之前还没有用过链式前向星这种建图方法,这里简述一下。其中edge[i].to表示第i条边的终点,edge[i].next表示与第i条边同起点的下一条边的存储位置,edge[i].w为边权值.另外还有一个数组head[],它是用来

表示以i为起点的第一条边存储的位置。实际上你会发现这里的第一条边存储的位置其实在以i为起点的所有边的最后输入的那个编号。head[]数组一般初始化为-1,对于加边的add函数是这样的。初始化一个变量num为0来记录当前总共的边的个数。

  附一篇大佬的博客:博客链接

再附上我的邻接表建图的代码:这个较慢一点

 1 #include <iostream>
 2 #include <cstring>
 3 #include <vector>
 4 #include <queue>
 5 using namespace std;
 6 
 7 const int maxn = 100 + 5;
 8 const double INF = 0x3f3f3f3f;
 9 struct node {
10     int to;
11     double commission;
12     double rate;
13 };
14 vector<node> G[maxn];
15 double dist[maxn];
16 bool vis[maxn];
17 int n, m, s;
18 double v;
19 bool ans;
20 
21 bool spfa() {
22     memset(vis, false, sizeof vis);
23     for(int i = 1; i <= n; i ++)
24         dist[i] = 0;
25     dist[s] = v;
26     queue <int> Q;
27     Q.push(s);
28     while(!Q.empty()) {
29         int now = Q.front(); Q.pop();
30         for(int i = 0; i < G[now].size(); i ++) {
31             node next = G[now][i];
32             if(dist[next.to] < (dist[now] - next.commission) * next.rate) {
33                 dist[next.to] = (dist[now] - next.commission) * next.rate;
34                 if(!vis[next.to]) Q.push(next.to);
35             }
36         }
37         if(dist[s] > v) return true;
38     }
39     return false;
40 }
41 
42 void addedge(int u, int v, double c, double r) {
43     G[u].push_back({v, c, r});
44 }
45 
46 int main () {
47     ios::sync_with_stdio(false);
48     int s1, s2;
49     double r1, c1, r2, c2;
50     ans = false;
51     cin >> n >> m >> s >> v;
52     for(int i = 0; i < m; i ++) {
53         cin >> s1 >> s2 >> r1 >> c1 >> r2 >> c2;
54         addedge(s1, s2, c1, r1);
55         addedge(s2, s1, c2, r2);
56     }
57     ans = spfa();
58     if(ans) cout << "YES" << endl;
59     else cout << "NO" << endl;
60     return 0;
61 }
View Code

猜你喜欢

转载自www.cnblogs.com/bianjunting/p/10699565.html