1. Dijkstra算法
   这个算法和prime求最小生成树特别像,都是找到最小边,把点加进来,然后用新加的点更新其他没有被加进来的点。
    1 .
      
#define  N 1002
   
2 .
      
#define  MAX 99999
   
3 .
      
int  edges[N][N],d[N],n;
   
4 .
       
   
5 .
      
void  dijkstra( int  v)
   
6 .
      {
   
7 .
              
int  i,j;
   
8 .
              
bool  s[N] = { false };
   
9 .
              
for (i = 1 ;i <= n;i ++ )
  
10 .
                      d[i]
= edges[v][i];
  
11 .
              d[v]
= 0 ;s[v] = true ;
  
12 .
              
for (i = 1 ;i < n;i ++ )
  
13 .
              {
  
14 .
                      
int  temp = MAX;
  
15 .
                      
int  u = v;
  
16 .
                      
for (j = 1 ;j <= n;j ++ )
  
17 .
                              
if (( ! s[j]) && (d[j] < temp))
  
18 .
                              {
  
19 .
                                      u
= j;
  
20 .
                                      temp
= d[j];
  
21 .
                              }
  
22 .
                              s[u]
= true ;
  
23 .
                              
for (j = 1 ;j <= n;j ++ )
  
24 .
                                      
if (( ! s[j]) && (edges[u][j] < MAX) && (d[u] + edges[u][j]) < d[j])
  
25 .
                                              d[j]
= d[u] + edges[u][j];
  
26 .
              }
  
27 .
       
  
28 .
      }

2. SPFA算法 (shortest path faster algorithm)
    不断维护一个队列,如果队列里的点,使得其他点的最短路得到松弛,则这个点还有可能使另外的点松弛,所以如果这个点不在队列里,就把它入队。
    很多时候,给定的图存在负权边,这时类似Dijkstra等 算法 便没有了用武之地,而Bellman-Ford 算法 的复杂度又过高, SPFA 算法 便派上用场了。 此算法时间复杂度为O(2*E),E为边数。
  // pku1860 
    #include < stdio.h >
    #include
< string .h >
    #include
< vector >
    
#define  N 120
    
using   namespace  std;
    
struct  Point
    {
        
int  id;
        
double  r, c;
    };
    vector
< Point >  p[N];
    
int  q[N],n,m,S,visit[N];
    
double  V,dist[N];
    
int  spfa()
    {
        memset(visit, 
0 sizeof (visit));
        
int  i,j,head = 0 ,tail = 1 ,x;
        
for (i = 1 ; i <= n ;i ++ )
            dist[i]
= 0 ;     // 此题是求换得的货币最多,所以初值赋0;
                          
// 若求最短路,初值应赋为无穷大
         if (V <= 0 return   0 ;
        q[
0 ] = S;
        dist[S]
= V;         // S为源,若求最短路,则dist[S]=0;
        visit[S] = 1 ;
        
while (head != tail){  //  Attention!!!由于对队列长度取模了,所以head<tail不一定成立,应改为head!=tail
            x = q[head];
            visit[x]
= 0 ;
            head
= (head + 1 ) % N;
            
for (i = 0 ; i < p[x].size(); i ++ ){

                j
= p[x][i].id;
                
if (dist[j] < (dist[x] - p[x][i].c) * p[x][i].r){
                    dist[j]
= (dist[x] - p[x][i].c) * p[x][i].r;
                    
if ( ! visit[j]){
                        q[tail]
= j;
                        tail
= (tail + 1 ) % N;
                        visit[j]
= 1 // 若如果j点的最短路径估计值有所调整,
                                    
//  且j点不在当前的队列中,就将j点放入队尾
                    }
                }
            }
            
if (dist[S] > V)  return   1 ;
        }
        
return   0 ;
    }
    
int  main()
    {
        
int  i,j,a,b;
        
double  rab, cab, rba, cba;
        Point p1, p2;
        
while (scanf( " %d %d %d %lf " , & n,  & m,  & S,  & V) != EOF){
            
for (i = 1 ; i <= n; i ++ )
                p[i].clear();
        
for (i = 0 ; i < m; i ++ ){
            scanf(
" %d %d %lf %lf %lf %lf " , & a,  & b,  & rab,  & cab,  & rba,  & cba);
            p1.id
= b; p1.r = rab; p1.c = cab;
            p2.id
= a; p2.r = rba; p2.c = cba;
            p[a].push_back(p1);
            p[b].push_back(p2);
        }
        j
= spfa();
        
if (j)
            printf(
" YES\n " );
        
else
            printf(
" NO\n " );
        }
        
return   0 ;
    }