E - Currency Exchange SPFA 判正权回路

https://vjudge.net/contest/375481#problem/E

一开始很快写完了判正权回路的代码 ,但是一直超时 ,发现错误是st【j】数组的添加一定要在数组特判条件内,没注意到。

总体思路:由题意可知,最终货币要要变成s,即变成原来货币。还要非负,所以就是要求出是否存在一个正权回路。

1.先给a,b 双向加边(加边代表的是货币的兑换流程线)

2.在SPFA函数里 用队列来存需要更新的点 

3.遍历每个需要更新的点的出边 做数值特判 符合比之前的钱多的条件 则存在正权边 然后把这个点的cnt【j】用上一个点cnt[t]的数值更新;

4.如果cnt[j]大于n-1条边 抽屉原理 即必定存在正权回路 ,否则不存在。

 

#include
#include
#include
#include
using namespace std;
const int N=110;
int e[N*2],ne[N*2],h[N*2],cnt[2*N];  //双向边开两倍
double dist[N],w1[2*N],w2[2*N];
int n,m,s,idx;
double v;
bool st[N];

void add(int a,int b,double c,double d)
{
    e[idx]=b,w1[idx]=c,w2[idx]=d,ne[idx]=h[a],h[a]=idx++;
}
bool SPFA()
{
    queueq;
    dist[s]=v;
    st[s]=true;
    q.push(s);
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dist[j]<(dist[t]-w2[i])*w1[i]) 
            {
                dist[j]=(dist[t]-w2[i])*w1[i];
                cnt[j]=cnt[t]+1;   //把上一个边的正权边数+1
            
                if(cnt[j]>=n) return true; //正权边数大于n-1条即一定存在正权回路
                    if(!st[j]) // 给st赋值一定要在 特判条件内 因为这样的j才是符合条件的
                {
                    q.push(j);
                    st[j]=true;
                }
            }
        }
        
    }
    return false;
}
int main()
{
    cin>>n>>m>>s>>v;
    memset(h,-1,sizeof h);
    for(int i=0;i>rate>>cost;
        add(a,b,rate,cost);
        cin>>rate>>cost;
        add(b,a,rate,cost);

    }
    if(SPFA()) cout<<"YES";
    else cout<<"NO";
    
}

 

你可能感兴趣的:(算法)