POJ 1860(spfa)
http://poj.org/problem?id=1860
题意:汇率转换,与之前的2240有点类似,不同的是那个题它去换钱的时候,是不需要手续费的,这个题是需要手续费的,这是个很大的不同。
思路:还是转换成为最短路的问题,主要的困难也就是关于它的松弛方程。dist [edge[i].v] < (dist[ tmp ] - edge[ i ].r) * edge[ i ].c 。这个就是松弛方程,当它的钱的数目增多的时候松弛。
1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 5 using namespace std; 6 7 8 int m,n,p,head[ 10005 ],pos,num[ 10005 ]; 9 bool vis[ 10005 ]; 10 double val,dist[ 10005 ]; 11 12 struct note{ 13 int v,next; 14 double r,c; 15 }edge[ 10005 ]; 16 17 void add(int x,int v,double r,double c) 18 { 19 edge[ pos ].v = v; 20 edge[ pos ].r = r; 21 edge[ pos ].c = c; 22 edge[ pos ].next = head[ x ]; 23 head[ x ] = pos ++; 24 } 25 26 bool spfa() 27 { 28 queue<int >s; 29 s.push(p); 30 dist[ p ] = val; 31 vis[ p ] = true; 32 num[ p ] ++; 33 while(!s.empty()) 34 { 35 int tmp = s.front(); 36 s.pop(); 37 vis[ tmp ] = false; 38 for( int i = head[ tmp ] ; i != -1 ; i = edge[ i ].next) 39 { 40 if( dist[ edge[ i ].v ] < (dist[ tmp ] - edge[ i ].c ) * edge[ i ].r ) 41 { 42 dist[ edge[ i ].v ] = (dist[ tmp ] - edge[ i ].c ) * edge[ i ].r; 43 if( !vis[ edge[ i ].v ] ) 44 { 45 s.push( edge[ i ].v ); 46 vis[ edge[ i ].v ] = true; 47 num[ edge[ i ].v ] ++; //可能构成正权回路,这个是用来判断的。但次数比m次要大的时候,就肯定是增多的。可以直接return 。 48 if( num[edge[ i ].v] > m) 49 return true; 50 } 51 } 52 } 53 } 54 if( dist[ p ] > val ) return true; //如果之后的钱比之前的多,也return true. 55 return false; 56 } 57 58 int main() 59 { 60 // freopen("in.txt","r",stdin); 61 int a,b; 62 double r1,c1,r2,c2; 63 pos = 1; 64 memset( head , -1 , sizeof( head ) ); 65 memset( dist , 0 , sizeof( dist ) ); 66 memset( vis , false ,sizeof( vis ) ); 67 memset( num , 0 , sizeof( num ) ); 68 scanf("%d%d%d%lf",&m,&n,&p,&val); 69 for( int i = 1 ; i <= n ; i++ ) 70 { 71 scanf("%d%d%lf%lf%lf%lf",&a,&b,&r1,&c1,&r2,&c2); 72 add(a,b,r1,c1); 73 add(b,a,r2,c2); 74 } 75 if(spfa()) printf("YES\n"); 76 else printf("NO\n"); 77 return 0; 78 }