hdu 1385 求字典序最小的最短路
需要注意的是这个题不仅有边权还有点权,起点和终点的点权不算。
思路还是一样,只是把路过的点的点权也加上再松弛即可。另外,距离相等的时候需要判断一下,选择字典序小的链连到这个点,方法就是把这个点以及之前的点放到栈里比较。
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <stack> 5 #include <cstdio> 6 using namespace std; 7 8 const int INF = 100000001; 9 const int N = 10001; 10 int graph[N][N]; 11 int dist[N]; 12 int tax[N]; 13 int pre[N]; 14 bool visit[N]; 15 int n, m; 16 17 bool lessThan( int cur, int x, int y ) 18 { 19 stack<int> sx, sy; 20 //注意:cur必须也放到栈里 21 sx.push(cur); 22 sy.push(cur); 23 while ( x != -1 ) 24 { 25 sx.push(x); 26 x = pre[x]; 27 } 28 while ( y != -1 ) 29 { 30 sy.push(y); 31 y = pre[y]; 32 } 33 while ( !sx.empty() && !sy.empty() ) 34 { 35 if ( sx.top() != sy.top() ) return sx.top() < sy.top(); 36 sx.pop(); 37 sy.pop(); 38 } 39 return sx.size() < sy.size(); 40 } 41 42 void dij( int s, int t ) 43 { 44 memset( visit, false, sizeof(visit) ); 45 for ( int i = 0; i <= n; i++ ) 46 { 47 dist[i] = INF; 48 } 49 dist[s] = 0; 50 pre[s] = -1; 51 for ( int i = 1; i <= n; i++ ) 52 { 53 int u = 0; 54 for ( int j = 1; j <= n; j++ ) 55 { 56 if ( !visit[j] && dist[j] < dist[u] ) 57 { 58 u = j; 59 } 60 } 61 visit[u] = true; 62 for ( int j = 1; j <= n; j++ ) 63 { 64 if ( visit[j] ) continue; 65 int d = dist[u] + graph[u][j] + tax[j]; 66 if ( d < dist[j] ) 67 { 68 dist[j] = d; 69 pre[j] = u; 70 } 71 else if ( d == dist[j] && lessThan( j, u, pre[j] ) ) 72 { 73 pre[j] = u; 74 } 75 } 76 } 77 } 78 79 void out( int i ) 80 { 81 if ( pre[i] == -1 ) 82 { 83 printf("Path: %d", i); 84 } 85 else 86 { 87 out( pre[i] ); 88 printf("-->%d", i); 89 } 90 } 91 92 int main () 93 { 94 while ( scanf("%d", &n), n ) 95 { 96 for ( int i = 1; i <= n; i++ ) 97 { 98 for ( int j = 1; j <= n; j++ ) 99 { 100 scanf("%d", &graph[i][j]); 101 if ( graph[i][j] == -1 ) 102 { 103 graph[i][j] = INF; 104 } 105 } 106 } 107 for ( int i = 1; i <= n; i++ ) 108 { 109 scanf("%d", tax + i); 110 } 111 int s, t; 112 while ( scanf("%d%d", &s, &t) != EOF ) 113 { 114 if ( s == -1 || t == -1 ) break; 115 int tmp = tax[t]; 116 tax[t] = 0; 117 dij( s, t ); 118 tax[t] = tmp; 119 printf("From %d to %d :\n", s, t); 120 out( t ); 121 printf("\nTotal cost : %d\n\n", dist[t]); 122 } 123 } 124 return 0; 125 }