1. 程式人生 > >Arbitrage 【HDU - 1217】【SPFA最短路】

Arbitrage 【HDU - 1217】【SPFA最短路】

題目連結


  關於SPFA是一道很不錯的題,也有人用弗洛伊德去寫的,然而……我一開始就是用Dijkstra去某名奇妙的WA了一發…… 然後沒有任何想法!不知道WA在哪了,後來,一想,原來是其中可能存在無限迴圈的自環,因為他們可能存在相當於負環,而這道題的Yes的條件,就是必須得存在這樣的負環,所以,我們有可能得走幾遍這樣的負環,得到最後的答案。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define efs 1e-7
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 35;
int N, M, cnt, head[maxN], num[maxN];
bool inque[maxN];
double dis[maxN];
string money, m1, m2;
map<string, int> mp;
struct Eddge
{
    int nex, to;
    double val;
    Eddge(int a=0, int b=0, double c=0):nex(a), to(b), val(c) {}
}edge[maxN*maxN];
inline void addEddge(int u, int v, double val)
{
    edge[cnt] = Eddge(head[u], v, val);
    head[u] = cnt++;
}
bool Spfa(int pos)
{
    memset(dis, 0, sizeof(dis));
    dis[pos] = 1.;
    queue<int> Q;
    Q.push(pos);
    num[pos]++;
    inque[pos] = true;
    while(!Q.empty())
    {
        int u = Q.front();    Q.pop();
        inque[u] = false;
        for(int i=head[u]; i!=-1; i=edge[i].nex)
        {
            int v = edge[i].to;
            double cost = edge[i].val;
            if(v == pos && dis[u] * cost > 1.) return true;
            if(dis[v] < dis[u] * cost && num[v] <= N)
            {
                dis[v] = dis[u] * cost;
                num[v]++;
                if(!inque[v])
                {
                    Q.push(v);
                    inque[v] = true;
                }
            }
        }
    }
    return false;
}
inline void init()
{
    cnt = 0;
    memset(head, -1, sizeof(head));
    memset(num, 0, sizeof(num));
    memset(inque, false, sizeof(inque));
}
int main()
{
    int Cas = 0;
    while(scanf("%d", &N) && N)
    {
        init();
        for(int i=1; i<=N; i++)
        {
            cin>>money;
            mp[money] = i;
        }
        scanf("%d", &M);
        while(M--)
        {
            double val;
            cin>>m1>>val>>m2;
            addEddge(mp[m1], mp[m2], val);
        }
        printf("Case %d: ", ++Cas);
        printf("%s\n", Spfa(1)?"Yes":"No");
    }
    return 0;
}