这道题中,边权属于[0,1],并且多段路的长度为各段的乘积。联系dijstra算法的特点,我们可以采取类似于dijstra的贪心策略,每次选取到源点距离最大的点,因为现在源点到其他的点的距离都不大于这个距离,以后如果再加上某一段,总的长度便会乘上一个不大于1的数字,就更不可能比现在选取的这个距离大了,所以按照和dijstra算法一样的流程可以求出“最安全的路”。
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 const double eps = 1e-4; 8 const int N = 1001; 9 double g[N][N]; 10 double dist[N]; 11 bool visit[N]; 12 int n, m; 13 14 void dij( int s ) 15 { 16 memset( visit, false, sizeof(visit) ); 17 for ( int i = 0; i <= n; i++ ) 18 { 19 dist[i] = 0; 20 } 21 dist[s] = 1; 22 for ( int i = 1; i <= n; i++ ) 23 { 24 int u = 0; 25 for ( int j = 1; j <= n; j++ ) 26 { 27 if ( !visit[j] && dist[j] > dist[u] ) 28 { 29 u = j; 30 } 31 } 32 visit[u] = true; 33 for ( int j = 1; j <= n; j++ ) 34 { 35 if ( !visit[j] && g[u][j] > eps ) 36 { 37 if ( dist[u] * g[u][j] > dist[j] ) 38 { 39 dist[j] = dist[u] * g[u][j]; 40 } 41 } 42 } 43 } 44 } 45 46 int main () 47 { 48 while ( scanf("%d", &n) != EOF ) 49 { 50 for ( int i = 1; i <= n; i++ ) 51 { 52 for ( int j = 1; j <= n; j++ ) 53 { 54 scanf("%lf", &g[i][j]); 55 } 56 } 57 scanf("%d", &m); 58 while ( m-- ) 59 { 60 int s, t; 61 scanf("%d%d", &s, &t); 62 dij(s); 63 if ( dist[t] < eps ) 64 { 65 printf("What a pity! "); 66 } 67 else 68 { 69 printf("%.3lf ", dist[t]); 70 } 71 } 72 } 73 return 0; 74 }