[洛谷P1931] 套利

Description

给定多组数据 每组数据给定n种货币 再给定m种货币之间的汇率 求是否存在一个环 使得汇率的积>1 即盈利

Solution

将每一中货币看作点 汇率看作边权

我们可以利用SPFA进行判断环 当一个点进行的松弛操作>=n时,即出现了一个环

这里要用最长路 将括号里的加号改为乘号 可以证明如果环上所有边

的权值之积大于1,那么一定可以用SPFA判定出有向图中存在环

因为如果小于1的话肯定越乘越小啊

无法出现盈利的情况有:

1  没有环 即最后没法回到原来的货币

2  有环 但是小于1

(有可能你要问程序里并没有判断是不是>1啊 你可以想想这是最长路)

Code

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <map>
 4 #include <cstring>
 5 #include <queue>
 6 using namespace std;
 7 int n, m, num, head[100], ok;
 8 int vis[100], times[100];
 9 double dis[100];
10 string s, ee;
11 map<string, int> mp;
12 struct emmm {
13     int next, to;
14     double dis;
15 }e[10000];
16 void add(int from, int to, double dis) {
17     e[++num].next = head[from];
18     e[num].to = to;
19     e[num].dis = dis;
20     head[from] = num;
21 }
22 int spfa(int s) {
23     memset(times, 0, sizeof(times));
24     memset(vis, 0, sizeof(vis));
25     memset(dis, 0, sizeof(dis));
26     queue<int>q;
27     q.push(s);
28     vis[s] = 1;
29     times[s] = 1;
30     dis[s] = 1.0;
31     while (!q.empty()) {
32         int now = q.front();
33         q.pop();
34         vis[now] = 0;
35         for (int i = head[now];i; i = e[i].next) {
36             int v = e[i].to;
37             if (dis[v] < dis[now] * e[i].dis) {
38                 dis[v] = dis[now] * e[i].dis;
39                 if (!vis[v]) {
40                     vis[v] = 1;
41                     q.push(v);
42                     times[v]++;
43                     if (times[v] >= n) return 1;
44                 }
45             }
46         }
47     }
48 
49     return 0;
50 }
51 int main() {
52     ios::sync_with_stdio(false);
53     cin >> n;
54     while (n) {
55         ++ok;
56         num = 0;
57         memset(e, 0, sizeof(e));
58         memset(head, 0, sizeof(head));
59         bool f = 0;
60         mp.clear();
61         for (int i = 1;i <= n; i++) 
62             mp[cin >> s, s] = i;
63         cin >> m;
64         double z;
65         for (int i = 1;i <= m; i++) {
66             cin >> s >> z >> ee;
67             add(mp[s], mp[ee], z);
68         }
69         for (int i = 1;i <= n; i++)
70             if (spfa(i)) {
71                 printf("Case %d: Yes\n", ok);
72                 f = 1;
73                 break;
74             }
75         if (f == 0) printf("Case %d: No\n", ok);
76         cin >> n;
77     }
78     return 0;
79 }
AC Code

 

 

posted @ 2019-08-17 12:17  _sheldon  阅读(247)  评论(0编辑  收藏  举报