Scandinavians often make vacation during the Easter holidays in the largest ski resort Are. Are provides fantastic ski conditions, many ski lifts and slopes of various difficulty profiles. However, some lifts go faster than others, and some are so popular that a queue forms at the bottom.
Per is a beginner skier and he is afraid of lifts, even though he wants to ski as much as possible. Now he sees that he can take several different lifts and then many different slopes or some other lifts, and this freedom of choice is starting to be too puzzling...
He would like to make a ski journey that:
Can you help Per find the least scary ski journey? A ski resort contains n places, m slopes, and k lifts (2 <= n <= 1000, 1 <= m <= 1000, 1 <= k <= 1000). The slopes and lifts always lead from some place to another place: the slopes lead from places with higher altitude to places with lower altitude and lifts vice versa (lifts cannot be taken downwards).
Input
The first line of the input contains the number of cases - the number of ski resorts to process. Each ski resort is described as follows: the first line contains three integers n, m, and k. The following m lines describe the slopes: each line contains three integers - top and bottom place of the slope (the places are numbered 1 to n), and the time it takes to go down the slope (max. 10000). The final k lines describe the lifts by three integers - the bottom and top place of the lift, and the time it takes to wait for the lift in the queue and be brought to its top station (max. 10000). You can assume that no two places are connected by more than one lift or by more than one slope.
Output
For each input case, the program should print two lines. The first line should contain a space-separated list of places in the order they will be visited - the first place should be the same as the last place. The second line should contain the ratio of the time spent in the slopes to the time spent on the lifts or wating for the lifts. The ratio should be rounded to the closest 1/1000th. If there are two possibilities, then the rounding is away from zero (e.g., 1.9812 and 1.9806 become 1.981, 3.1335 becomes 3.134, and 3.1345 becomes 3.135). If there are multiple journeys that prior to rounding are equally scary, print an arbitrary one.
Sample Input
1 5 4 3 1 3 12 2 3 6 3 4 9 5 4 9 4 5 12 5 1 12 4 2 18
Sample Output
4 5 1 3 4 0.875
题意:
给你一个滑雪场,有两种边(用雪橇上升可看做一种边,从雪坡滑下来可看做一种边),让你找到两点A、B,A->B为经过第一种边上去,所需时间t1,B->A为经过第二种边下来,所需时间t2,使得t2/t1最大。
思路:
用两种边分别建两个图,用n次SPFA找到一个图中的任意一点到任意一点的最短路,再用n次SPFA找到另一个图中的任意一点到任意一点的最长路,然后枚举取得t2/t1的最大值就够了。
这肯定是我写的最揪心的一次代码了,自己写着写着就乱了。。。要注意的是递归打印路径 以及邻接表的建立,在结构体数组里多加了一个变量next,具体用法见加边函数。
1 #include<stdio.h> 2 #include<string.h> 3 #include<queue> 4 using namespace std; 5 6 const int INF = 0x3f3f3f3f; 7 const int maxn = 1100; 8 struct node 9 { 10 int v,w; 11 int next; 12 }edge1[maxn],edge2[maxn]; 13 14 int n,m,k; 15 int cnt;//边数; 16 int p[maxn];//保存与起始顶点u有边相连的那些边对应的下标,相当于邻接表; 17 int dis1[maxn][maxn],dis2[maxn][maxn];//dis[i][j]表示i为源点到j的最短路; 18 int parent1[maxn][maxn],parent2[maxn][maxn];//parent[i][j]表示以i为源点,j的前驱 19 int start,end; 20 queue<int>que; 21 22 void init() 23 { 24 memset(parent1,0,sizeof(parent1)); 25 memset(parent2,0,sizeof(parent2)); 26 memset(dis1,0,sizeof(dis1)); 27 memset(dis2,INF,sizeof(dis2)); 28 } 29 void add_edge_1(int u, int v, int w)//建第一个图 30 { 31 cnt++; 32 edge1[cnt].v = v; 33 edge1[cnt].w = w; 34 edge1[cnt].next = p[u]; 35 p[u] = cnt; 36 } 37 38 void add_edge_2(int u, int v, int w)//建第二个图 39 { 40 cnt++; 41 edge2[cnt].v = v; 42 edge2[cnt].w = w; 43 edge2[cnt].next = p[u]; 44 p[u] = cnt; 45 } 46 void spfa1(int s)//spfa求最长路,dis1[][]初始化为最小 47 { 48 int inque[maxn]; 49 while(!que.empty()) 50 que.pop(); 51 memset(inque,0,sizeof(inque)); 52 53 parent1[s][s] = s; 54 dis1[s][s] = 0; 55 que.push(s); 56 inque[s] = 1; 57 58 while(!que.empty()) 59 { 60 int u = que.front(); 61 que.pop(); 62 inque[u] = 0; 63 64 for(int i = p[u];i;i = edge1[i].next)//注意p数组在这里的用法,找所有与u相连的边的下标 65 { 66 if(dis1[s][edge1[i].v] < dis1[s][u] + edge1[i].w) 67 { 68 dis1[s][edge1[i].v] = dis1[s][u] + edge1[i].w; 69 parent1[s][edge1[i].v] = u; 70 if(!inque[edge1[i].v]) 71 { 72 inque[edge1[i].v] = 1; 73 que.push(edge1[i].v); 74 } 75 } 76 } 77 } 78 } 79 80 void spfa2(int s)//spfa求最短路,dis2[][]初始化为最大 81 { 82 int inque[maxn]; 83 while(!que.empty()) que.pop(); 84 memset(inque,0,sizeof(inque)); 85 86 parent2[s][s] = s; 87 dis2[s][s] = 0; 88 que.push(s); 89 inque[s] = 1; 90 91 while(!que.empty()) 92 { 93 int u = que.front(); 94 que.pop(); 95 inque[u] = 0; 96 97 for(int i = p[u]; i; i = edge2[i].next) 98 { 99 if(dis2[s][edge2[i].v] > dis2[s][u] + edge2[i].w) 100 { 101 dis2[s][edge2[i].v] = dis2[s][u] + edge2[i].w; 102 parent2[s][edge2[i].v] = u; 103 if(!inque[edge2[i].v]) 104 { 105 inque[edge2[i].v] = 1; 106 que.push(edge2[i].v); 107 } 108 } 109 } 110 } 111 } 112 void output2(int e, int s)//递归打印路径2(A->B) 113 { 114 if(e == s) 115 printf("%d",e); 116 else 117 { 118 output2(parent2[s][e],s); 119 printf(" %d",e); 120 } 121 } 122 void output1(int e,int s) //递归打印路径1(B->A) 123 { 124 if(e==s) return; 125 else 126 { 127 output1(parent1[s][e],s); 128 printf(" %d",e); 129 } 130 } 131 int main() 132 { 133 int test; 134 scanf("%d",&test); 135 while(test--) 136 { 137 scanf("%d %d %d",&n,&m,&k); 138 init(); 139 140 cnt = 0; 141 memset(p,0,sizeof(p)); 142 for(int i = 0; i < m; i++) 143 { 144 int u,v,w; 145 scanf("%d %d %d",&u,&v,&w); 146 add_edge_1(u,v,w); 147 } 148 for(int i = 1; i <= n; i++) 149 { 150 spfa1(i); 151 } 152 153 cnt = 0; 154 memset(p,0,sizeof(p)); 155 for(int i = 0; i < k; i++) 156 { 157 int u,v,w; 158 scanf("%d %d %d",&u,&v,&w); 159 add_edge_2(u,v,w); 160 } 161 for(int i = 1; i <= n; i++) 162 { 163 spfa2(i); 164 } 165 166 double ans = 0; 167 //枚举查找满足t2/t1最大的起始点A,B; 168 for(int i = 1; i <= n; i++) 169 { 170 for(int j = 1; j <= n; j++) 171 { 172 if(i == j || dis2[i][j] == INF) 173 continue; 174 if(dis1[j][i]*1.0/dis2[i][j] > ans) 175 { 176 ans = dis1[j][i]*1.0/dis2[i][j]; 177 start = i;//A 178 end = j;//B 179 } 180 } 181 } 182 output2(end,start); 183 output1(start,end); 184 printf("\n"); 185 printf("%.3lf\n",ans); 186 } 187 return 0; 188 }