• POJ1680 Currency Exchange SPFA判正环


    转载来源:優YoU  http://user.qzone.qq.com/289065406/blog/1299337940

    提示:关键在于反向利用Bellman-Ford算法

    题目大意

    有多种汇币,汇币之间可以交换,这需要手续费,当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加

    货币的交换是可以重复多次的,所以我们需要找出是否存在正权回路,且最后得到的s金额是增加的

    怎么找正权回路呢?(正权回路:在这一回路上,顶点的权值能不断增加即能一直进行松弛)

    题目分析:

    一种货币就是图上的一个点

    一个“兑换点”就是图上两种货币之间的一个兑换环,相当于“兑换方式”M的个数,是双边

    唯一值得注意的是权值,当拥有货币A的数量为V时,A到A的权值为K,即没有兑换

    而A到B的权值为(V-Cab)*Rab

    本题是“求最大路径”,之所以被归类为“求最小路径”是因为本题题恰恰与bellman-Ford算法的松弛条件相反,求的是能无限松弛的最大正权路径,但是依然能够利用bellman-Ford的思想去解题。

    因此初始化d(S)=V   而源点到其他店的距离(权值)初始化为无穷小(0),当s到其他某点的距离能不断变大时,说明存在最大路径

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const int N=1e2+5;
    struct Edge{
       int v,next;
       double r,c; 
    }edge[N*2];
    int n,m,s,head[N],tot,cnt[N];
    bool inq[N];
    double d[N],v;
    queue<int>q;
    void add(int u,int v,double r,double c){
       edge[tot].v=v;
       edge[tot].r=r;
       edge[tot].c=c;
       edge[tot].next=head[u];
       head[u]=tot++;
    }
    bool spfa(int s){
       memset(d,0,sizeof(d));
       memset(inq,0,sizeof(inq));
       memset(cnt,0,sizeof(cnt));
       d[s]=v,q.push(s),inq[s]=true,cnt[s]=1;
       while(!q.empty()){
         int u=q.front();
         q.pop();
         inq[u]=false;
         for(int i=head[u];~i;i=edge[i].next){
            int to=edge[i].v;
            double r=edge[i].r,c=edge[i].c;
            if(d[to]<r*(d[u]-c)){
               d[to]=r*(d[u]-c);
               if(!inq[to]){
                  inq[to]=true;
                  if(++cnt[to]>n)return true;
                  q.push(to);
               }  
            }
         }
         if(d[s]>v)return true;
       }
       return false;
    }
    int main(){
        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 r,c;
           scanf("%d%d%lf%lf",&u,&v,&r,&c);
           add(u,v,r,c);
           scanf("%lf%lf",&r,&c);
           add(v,u,r,c); 
        }
        if(spfa(s))printf("YES
    ");
        else printf("NO
    ");
        return 0;
    }
    View Code
  • 相关阅读:
    阻止用户复制页面上的文字的几种方法
    js设置聊天信息停留在最底部
    js动态删除表格中的某一行
    XmlSerializer vs DataContractSerializer: Serialization in Wcf
    WCF Service Binding Explained
    Visual Studio设置远程调试
    Could not download the Silverlight application
    .NET 中的三种接口实现方式
    化零为整WCF(9) 序列化(DataContractSerializer, XmlSerializer, DataContractJsonSerializer, SoapFormatter, BinaryFormatter)
    化零为整WCF(14) 事务(Transaction)
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5314754.html
Copyright © 2020-2023  润新知