Arbitrage HDU - 1217 弗洛伊德/SPFA

Arbitrage

Arbitrage is the use of discrepancies in currency exchange rates to transform one unit of a currency into more than one unit of the same currency. For example, suppose that 1 US Dollar buys 0.5 British pound, 1 British pound buys 10.0 French francs, and 1 French franc buys 0.21 US dollar. Then, by converting currencies, a clever trader can start with 1 US dollar and buy 0.5 * 10.0 * 0.21 = 1.05 US dollars, making a profit of 5 percent.

Your job is to write a program that takes a list of currency exchange rates as input and then determines whether arbitrage is possible or not.
Input
The input file will contain one or more test cases. Om the first line of each test case there is an integer n (1<=n<=30), representing the number of different currencies. The next n lines each contain the name of one currency. Within a name no spaces will appear. The next line contains one integer m, representing the length of the table to follow. The last m lines each contain the name ci of a source currency, a real number rij which represents the exchange rate from ci to cj and a name cj of the destination currency. Exchanges which do not appear in the table are impossible.
Test cases are separated from each other by a blank line. Input is terminated by a value of zero (0) for n.
Output
For each test case, print one line telling whether arbitrage is possible or not in the format “Case case: Yes” respectively “Case case: No”.
Sample Input
3
USDollar
BritishPound
FrenchFranc
3
USDollar 0.5 BritishPound
BritishPound 10.0 FrenchFranc
FrenchFranc 0.21 USDollar

3
USDollar
BritishPound
FrenchFranc
6
USDollar 0.5 BritishPound
USDollar 4.9 FrenchFranc
BritishPound 10.0 FrenchFranc
BritishPound 1.99 USDollar
FrenchFranc 0.09 BritishPound
FrenchFranc 0.19 USDollar

0
Sample Output
Case 1: Yes
Case 2: No

题意

大致的意思就是给我们一个汇率的关系 去判断你能否根据利率关系获利

方案
  1. 弗洛伊德
    这道题因为数据范围很友好 所以弗洛伊德是个很好的选择 我们把利率关系看做边 就可以得到式子 dis[i] = max(dis[i],利率*dis[j]) 然后跑一遍弗洛伊德看自身的值有没有大于 1 就好
  2. SPFA
    这道题有些类似找负环 为什么呢 当我们跑最短路的时候有负环最短路没有最小值 因为会一直循环在最短路中 这道题也类似 如果可以盈利 那么我们的本金会一直上涨 没有最值 所以我们在代码中有这么一行代码 if(dis[1] > 1) return; 所以只需要跑一遍SPFA即可

弗洛伊德

#include<iostream>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<unordered_map>
#include<queue>
#include<vector>
#include<cstdlib>
#include<utility>
#include<cstring>
using namespace std;

map<string,int>mp;
int q,p;
double ans;
double vis[40][40];
string tmpa,tmpb;
unsigned int flag;
unsigned int eg;

int main()
{
    while(cin >> q && q!=0){
        flag=0;
        memset(vis,0,sizeof(vis));
        mp.clear();
        for(int i=0;i<q;++i){
            cin >> tmpa;
            mp[tmpa]=++flag;
            vis[flag][flag]=1;
        }
        cin >> p;
        for(int i=0;i<p;++i){
            cin >> tmpa >> ans >> tmpb;
            vis[mp[tmpb]][mp[tmpa]] = ans;
        }
        for(int i=1;i<=q;++i){
            for(int j=1;j<=q;++j){
                for(int k=1;k<=q;++k){
                    vis[j][k]=max(vis[j][k],vis[j][i]*vis[i][k]);
                }
            }
        }
        int key=0;
        for(int i=1;i<=q;++i){
            if(vis[i][i]>1){
                key=1;
                break;
            }
        }
        printf("Case %d: %s\n",++eg,key?"Yes":"No");
    }
    return 0;
}

SPFA

#include<iostream>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<unordered_set>
#include<unordered_map>
#include<queue>
#include<vector>
#include<cstdlib>
#include<utility>
#include<cstring>
using namespace std;

map<string,int>mp;
int m,n;
double w;
string tmpa,tmpb;
int flag;
struct node{
    double w;
    int to;
};
vector<node> G[36];
double dis[36];

void SPFA(){
    queue<int>que;
    unordered_set<int>se;
    memset(dis,0,sizeof(dis));
    dis[1] = 1.0;
    que.push(1);
    se.insert(1);
    while(!que.empty()){
        int temp = que.front();
        que.pop();
        se.erase(temp);
        for(auto x : G[temp]){
            if(x.w*dis[temp] > dis[x.to])
            {
                dis[x.to] = x.w*dis[temp];
                if(dis[1] > 1) return;
                if(se.find(x.to) == se.end()){
                    que.push(x.to);
                    se.insert(x.to);
                }
            }
/*             if(se.find(x.to) == se.end()){  //这个片段是错误的 会忽略一些情况 
                if(dis[1] > 1) return; 
                if(x.w*dis[temp] > dis[x.to]){
                    dis[x.to] = x.w*dis[temp];
                    se.insert(x.to);
                    que.push(x.to);
                }
            } */
        }
    }
}

main()
{
    int cas = 0;
    while(cin >> m && m){
        flag = 0;
        mp.clear();
        for(int i=0;i<36;++i) G[i].clear();
        for(int i=0;i<m;++i){
            cin >> tmpa;
            mp[tmpa] = ++flag;
        }
        cin >> n;
        for(int i=0;i<n;++i){
            cin >> tmpa >> w >> tmpb;
            G[mp[tmpa]].push_back({w,mp[tmpb]});//没有移动构造函数 不可以使用emplace 此处要好好研究
        }
        SPFA();
        printf("Case %d: %s\n", ++cas, dis[1] > 1.0 ? "Yes" : "No");
    }
    return 0;
}
posted @ 2022-07-02 13:18  李兆龙的博客  阅读(19)  评论(0编辑  收藏  举报