poj1860 Currency Exchange(spfa判断是否存在正环)

题意:有m个货币交换点,每个点只能有两种货币的互相交换,且要给佣金,给定一开始的货币类型和货币数量,问若干次交换后能否让钱增加。

思路:spfa求最长路,判断是否存在正环,如果存在则钱可以在环中一直增加,最后的钱肯定也是增加的。

#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
using namespace std;

const int maxn = 100 + 5;
struct edge{
    int to, next;
    double r, c;
} ed[maxn*2];
int n, m, s, inq[maxn];
int head[maxn], tot;
double v, dis[maxn];
bool vis[maxn];
inline void add( int u, int v, double r, double c ){
    ed[tot].to = v;
    ed[tot].r = r;
    ed[tot].c = c;
    ed[tot].next = head[u];
    head[u] = tot ++;
}

inline bool spfa(int start){
    queue<int> q;
    memset( vis, 0, sizeof(vis) );
    memset( dis, 0, sizeof(dis) );
    memset( inq, 0, sizeof(inq) );
    dis[s] = v;
    vis[s] = 1;
    q.push(s);
    while( q.size() ){
         int u = q.front();
         q.pop();
         vis[u] = 0;
         if( ++inq[u]>=n ) return 1;    //一个点进队列的次数大于等于点的数量n则存在环
         for( int i=head[u]; i!=-1; i=ed[i].next ){
             int v = ed[i].to;
             if( dis[v]<(dis[u]-ed[i].c)*ed[i].r ){
                 dis[v] = (dis[u]-ed[i].c)*ed[i].r;
                 if( !vis[v] ){
                     vis[v] = 1;
                     q.push(v);
                 }
             }
         }
    }
    return 0;
}

int main(){
    // freopen("in.txt", "r", stdin);
    scanf("%d%d%d%lf", &n, &m, &s, &v);
    memset( head, -1, sizeof(head) );
    tot = 0;
    for( int i=0; i<m; i++ ){
        int u, v;
        double ru, cu, rv, cv;
        scanf("%d%d%lf%lf%lf%lf", &u, &v, &ru, &cu, &rv, &cv);
        add( u, v, ru, cu );
        add( v, u, rv, cv );
    }
    if( spfa(s) ) puts("YES");
    else puts("NO");

    return 0;
}

 

posted @ 2019-05-28 13:13  CoffeeCati  阅读(279)  评论(0编辑  收藏  举报