您的位置:首页 > 其它

poj 1860 最短路径变形

2013-01-24 11:19 393 查看
Currency Exchange

Time Limit: 1000MSMemory Limit: 30000K
Total Submissions: 14000Accepted: 4808
Description
Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and performs exchange operations only with these currencies. There can be several points specializing in the same pair of currencies. Each point has its own exchange rates, exchange rate of A to B is the quantity of B you get for 1A. Also each exchange point has some commission, the sum you have to pay for your exchange operation. Commission is always collected in source currency.
For example, if you want to exchange 100 US Dollars into Russian Rubles at the exchange point, where the exchange rate is 29.75, and the commission is 0.39 you will get (100 - 0.39) * 29.75 = 2963.3975RUR.
You surely know that there are N different currencies you can deal with in our city. Let us assign unique integer number from 1 to N to each currency. Then each exchange point can be described with 6 numbers: integer A and B - numbers of currencies it exchanges, and real RAB, CAB, RBA and CBA - exchange rates and commissions when exchanging A to B and B to A respectively.
Nick has some money in currency S and wonders if he can somehow, after some exchange operations, increase his capital. Of course, he wants to have his money in currency S in the end. Help him to answer this difficult question. Nick must always have non-negative sum of money while making his operations.
Input
The first line of the input contains four numbers: N - the number of currencies, M - the number of exchange points, S - the number of currency Nick has and V - the quantity of currency units he has. The following M lines contain 6 numbers each - the description of the corresponding exchange point - in specified above order. Numbers are separated by one or more spaces. 1<=S<=N<=100, 1<=M<=100, V is real number, 0<=V<=103.
For each point exchange rates and commissions are real, given with at most two digits after the decimal point, 10-2<=rate<=102, 0<=commission<=102.
Let us call some sequence of the exchange operations simple if no exchange point is used more than once in this sequence. You may assume that ratio of the numeric values of the sums at the end and at the beginning of any simple sequence of the exchange operations will be less than 104.
Output
If Nick can increase his wealth, output YES, in other case output NO to the output file.
Sample Input
3 2 1 20.0
1 2 1.00 1.00 1.00 1.00
2 3 1.10 1.00 1.10 1.00

Sample Output
YES

题意:
    有n个点以及m*2条边;从s点出发,初始值为v。
    问从s点出发,回到s点,是否可以使v的值超过原始值。
  
解法:
    这是一道神奇的题目。。。才知道原来SPFA可以这样用。将原先的求最小值的SPFA改为求最大,那么如果每次转回出发点时,判断出发点的新值是否大于原始值,如果大于,那么则可跳出,直接得出“YES”
    关键是原来SPFA求负环的应用;因为被改为求最大,所以负环的存在现在变为环中的值在不断地增大,所以如果在判断存在负环后,可以得出:出发点上的值在不断地增大,只是在有限的范围内没有达到超过
    原始值,但终究会超过。所以只要存在负环,就可以输出“YES”。


#include<iostream>
#include<string.h>
#include<queue>
#include<stdio.h>
using namespace std;
#define maxver 1000
#define maxpoint 300
int first[maxpoint];
double w[maxver];
double c[maxver];
int next[maxver];
int v[maxver];
double d[maxpoint];
int times[maxpoint];
bool test[maxpoint];
int main(){
    int n,m,start;
    double value;
    while(scanf("%d%d%d%lf",&n,&m,&start,&value)!=EOF){                                     //cin the number of point and ver
          memset(first,-1,sizeof(first));
          memset(next,-1,sizeof(next));
          memset(times,0,sizeof(times));
          memset(d,0,sizeof(d));
         for(int i=1;i<=m;i++){
                 int temp1,temp2;
                 scanf("%d%d",&temp1,&temp2);
                 scanf("%lf%lf%lf%lf",&w[i],&c[i],&w[i+m],&c[i+m]);         //cin the ver's points and weigh
                 if(first[temp1]==-1){
                         first[temp1]=i;
                         }
                 else{
                         int temp3=first[temp1];
                         first[temp1]=i;
                         next[i]=temp3;
                         }
                 v[i]=temp2;
                 if(first[temp2]==-1){
                         first[temp2]=i+m;
                         }
                 else{
                         int temp4=first[temp2];
                         first[temp2]=i+m;
                         next[i+m]=temp4;
                         }
                 v[i+m]=temp1;
                 }
         
    queue <int> q;
    q.push(start);             //start from 0;
    d[start]=value;
    int flag=0;
    int res=0;
    double re=value;
    while(!q.empty()){
         flag=0;
         int p=q.front();
         if(p==start){
                 if(d[p]>re){
                   res=1;
                   break;
                 }
                 else
                   re=d[p];
                 }
         q.pop();
         test[p]=false;
         times[p]++;
         if(times[p]>=n){
                flag=1;
                break;
                }
         for(int k=first[p];k!=-1;k=next[k]){
                 if(((d[p]-c[k])*w[k])>d[v[k]]){
                       d[v[k]]=(d[p]-c[k])*w[k];
                       if(test[v[k]]==false){
                           test[v[k]]=true;
                           q.push(v[k]);
                           }
                           }
                           }
                           }
    if(flag==1){
           cout<<"YES"<<endl;             //exist 负环 
           }
   else{
        if(res==1)
          cout<<"YES"<<endl;
        else
          cout<<"NO"<<endl;
          }
            }
     return 0;
     }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: