POJ [2253] Arbitraje [SPFA juzga el anillo positivo]

Descripción

El arbitraje es el uso de discrepancias en las tasas de cambio de moneda para transformar una unidad de una moneda en más de una unidad de la misma moneda. Por ejemplo, suponga que 1 dólar estadounidense compra 0,5 libras británicas, 1 libra británica compra 10,0 francos franceses y 1 franco francés compra 0,21 dólares estadounidenses. Luego, al convertir monedas, un comerciante inteligente puede comenzar con 1 dólar estadounidense y comprar 0.5 * 10.0 * 0.21 = 1.05 dólares estadounidenses, obteniendo una ganancia del 5 por ciento.

Su trabajo es escribir un programa que tome una lista de los tipos de cambio de divisas como entrada y luego determine si el arbitraje es posible o no.

Entrada 

La entrada contendrá uno o más casos de prueba. En la primera línea de cada caso de prueba hay un número entero n (1 <= n <= 30), que representa el número de monedas diferentes. Las siguientes n líneas contienen cada una el nombre de una moneda. Dentro de un nombre no aparecerán espacios. La siguiente línea contiene un entero m, que representa la longitud de la tabla a seguir. Las últimas m líneas contienen el nombre ci de una moneda de origen, un número real rij que representa el tipo de cambio de ci a cj y un nombre cj de la moneda de destino. Los intercambios que no aparecen en la tabla son imposibles.
Los casos de prueba están separados entre sí por una línea en blanco. La entrada termina con un valor de cero (0) para n.

Salida 

Para cada caso de prueba, imprima una línea que indique si el arbitraje es posible o no en el formato "Caso de caso: Sí" respectivamente "Caso de caso: No".

Entrada de muestra 

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

Salida de muestra 

Caso 1: Sí 
Caso 2: No

La idea principal:

Dadas algunas monedas, y los tipos de cambio entre estas monedas, se requiere ver si pueden ganar más dinero que el original a través del cambio de moneda.

Análisis:

Una moneda puede verse como un punto en el gráfico, y un método de conversión es una ventaja entre las dos monedas en el gráfico.

Tenga en cuenta que los bordes aquí son bordes dirigidos.

Teniendo en cuenta los pesos de los bordes, los pesos de A a B son  V_A * R_A_B.

Se requiere aumentar la cantidad final, es decir, encontrar un anillo positivo en la imagen. De esta manera, el arbitraje siempre se puede lograr en el anillo positivo.

SPFA se utiliza aquí para juzgar el anillo positivo.

Vea el código para una explicación específica.

 

//#include <bits/stdc++.h>
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#include <map>
#include <cmath>
#include <vector>
#include <iomanip>

using namespace std;

const int maxn=1005;
const int INF=0x3f3f3f3f;

string names[35];
map<string,int> mp;

double dis[maxn];
int head[maxn];
int vis[maxn],times[maxn];

int ans;
int m,n,s;
double initv;

struct node{
    int u,v;
    double r;
    int next;
}edge[maxn];

void add(int u,int v,double r){
    edge[ans].u=u;
    edge[ans].v=v;
    edge[ans].r=r;
    edge[ans].next=head[u];
    head[u]=ans++;
}

bool spfa(int st){
    memset(vis, 0, sizeof(vis));
    memset(times, 0, sizeof(times));	//times数组记录顶点入队的次数 
    for(int i = 1; i<=n; i++)
        dis[i] = 0;				//初始化其他点的dis值为0

    queue<int> Q;
    Q.push(st);
    vis[st] = 1;
    dis[st] = 1;	//初始货币值为 1 
    while(!Q.empty()){
        int u = Q.front();
        Q.pop(); 
		vis[u] = 0;
        for(int i = head[u]; i!=-1; i = edge[i].next){	 
            int v = edge[i].v;
            if(dis[v] < dis[u]*edge[i].r){	//注意这里的松弛条件
                dis[v] = dis[u]*edge[i].r;
                if(!vis[v]){
                    Q.push(v);
                    vis[v] = 1;
                    if(++times[v]>n) return true;	//某一顶点入队超过 n次,则存在正环 
                }
            }
        }
    }
    return false;
}

int main(){
	int cas=0;
	while(cin>>n&&n){
		mp.clear();
		ans=0;
		++cas;
		memset(head,-1,sizeof(head));
		string tmp;
		int cnt=0;
		for(int i=1;i<=n;i++){
			cin>>tmp;
			names[++cnt]=tmp;
			mp[tmp]=cnt;	//这里将货币名称映射为整型数值 
		}
		cin>>m;
		string tmp1,tmp2;
		double rate;
		int index1,index2;
		for(int i=1;i<=m;i++){
			cin>>tmp1>>rate>>tmp2;
			index1=mp[tmp1];
			index2=mp[tmp2];
			add(index1,index2,rate);	//加入有向边 
		}
		if(spfa(1))  cout<<"Case "<<cas<<": "<<"Yes"<<endl;
		else  cout<<"Case "<<cas<<": "<<"No"<<endl;
	}
	return 0;
}

 

30 artículos originales publicados · ganó 5 · 900 visitas

Supongo que te gusta

Origin blog.csdn.net/qq_42840665/article/details/101941241
Recomendado
Clasificación