洛谷 P1931 套利 spfa 最长路变形 spfa相加变相乘

题目链接:

https://www.luogu.org/problem/P1931

类似题目:

https://blog.csdn.net/aiwo1376301646/article/details/100583424

思路:

1:方向:最长路的变形问题

2:把汇率表抽象成一个有向图,每个货币是一个结点,每条边上的权值就是汇率

3:无法套利的情况分两种:

      1:没有环,即最后无法回到该种货币

      2:有环,但是没有利率之积大于1的环

4:核心思想及注意事项:满足题意可以套利的情况需要满足两个条件:

      1:有环

      2:有利率之积大于1的环

思考我们判断是否有环的方法是,用一个数组times存每一个节点入队的次数,如果有环,那么同一个节点入队的次数将大于等于节点总个数即n个,又因为要使一个节点n次及以上入队,那么必须满足

if(d[v]<d[now]*e[now][i].second)

也就说明了,经过这一圈的转换,比原来的值大,(只有比原来的值大,才可以执行if条件里的代码,才可以实现times[v]>=n这一行代码)这也就说明了,是可以套利的,环的利率之积大于1,因此只要可以形成环,那么就一定满足可以套利(就是说,有环和环的利率之积大于1,这两个条件是相辅相成的,只要有环,那么就一定满足环的利率之积大于1,只有利率之积大于1,才可以形成环)

5:这道题目还应该特别注意,一定要初始化,因为涉及多组数据,如果不想初始化,那么就把要用到的结构写在main函数中,但缺点是调用函数时要做为参数传进去

#include <bits/stdc++.h>

using namespace std;
const int maxn=31;
vector<pair<int,double> >e[maxn];
int n,m,ing[maxn],cnt,num=1,times[maxn];
double d[maxn],c;
string a,b;
map<string,int>ma;

inline bool spfa(int s)
{
    memset(ing,0,sizeof(ing));
    memset(d,0,sizeof(d));
    memset(times,0,sizeof(times));
    queue<int>q;
    q.push(s);
    times[s]++;
    d[s]=1;
    ing[s]=1;
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        ing[now]=0;
        for(int i=0;i<e[now].size();i++)
        {
            int v=e[now][i].first;
            if(d[v]<d[now]*e[now][i].second)
            {
                d[v]=d[now]*e[now][i].second;
                if(ing[v])
                    continue;
                q.push(v);
                times[v]++;
                if(times[v]>=n)
                    return true;
                ing[v]=1;
            }
        }
    }
    return false;
}

int main()
{
    ios::sync_with_stdio(0);
    while(cin>>n&&n)
    {
        cnt=1;
        ma.clear();
        for(int i=1;i<=n;i++)
        {
            e[i].clear();
        }
        for(int i=1;i<=n;i++)
        {
            cin>>a;
            ma[a]=cnt++;
        }
        cin>>m;
        for(int i=1;i<=m;i++)
        {
            cin>>a>>c>>b;
            e[ma[a]].push_back(make_pair(ma[b],c));
        }
        bool flag=true;
        for(int i=1;i<=n;i++)
        {
            if(spfa(i))
            {
                cout<<"Case "<<num++<<": Yes"<<endl;
                flag=false;
                break;
            }
        }
        if(flag)
        cout<<"Case "<<num++<<": No"<<endl;
    }
    return 0;
}
发布了117 篇原创文章 · 获赞 37 · 访问量 6609

猜你喜欢

转载自blog.csdn.net/aiwo1376301646/article/details/100587494