题目描述 Description
又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两 个机场之间有一条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。
那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
任务
找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。
输入描述 Input Description
第一行为一个正整数n(0<=n<=10),表示有n组测试数据。
每组的第一行有四个正整数s,t,A,B。
S(0<S<=100)表示城市的个数,t表示飞机单位里程的价格,A,B分别为城市A,B的序号,(1<=A,B<=S)。
接下来有S行,其中第I行均有7个正整数xi1,yi1,xi2,yi2,xi3,yi3,Ti,这当中的(xi1,yi1),(xi2,yi2),(xi3,yi3)分别是第I个城市中任意三个机场的坐标,T I为第I个城市高速铁路单位里程的价格。
输出描述 Output Description
共有n行,每行一个数据对应测试数据。
样例输入 Sample Input
1
3 10 1 3
1 1 1 3 3 1 30
2 5 7 4 5 2 1
8 6 8 8 11 6 3
样例输出 Sample Output
47.5
分析
最短路的裸题= = 唯一存在的问题就是如何把“四源四终点”的最短路问题转化为复杂度较低的问题。借用刘汝佳《训练指南》上网络流建模的思路,这里不妨建立一个虚拟机场0,在0和城市A的四个机场各连一条权值为0的边,即可用单源最短路算法求解。另。。因为题目中边数E很接近n2,所以用Dijkstra会比SPFA快很多(2s和4s)。。。。别看我,我是写完SPFA之后才想起来的=_=||
2 // E-Mail: willywu1998@foxmail.com
3 #include <cstdio>
4 #include <deque>
5 #include <cmath>
6 #include <memory.h>
7 #include <iostream>
8 #define MAX 0x3f3f3f3f
9 #define mod(x) ( sqrt((x) * (x)) )
10 using namespace std;
11 struct v { // vector(location)
12 int x,y;
13 v (){};v( int a, int b):x(a),y(b){};
14 v operator +( const v& b) { return v(x+b.x,y+b.y);}
15 v operator -( const v& b) { return v(x-b.x,y-b.y);}
16 int operator * ( const v& b) { return x*b.x + y*b.y;}
17 };
18 inline v get4(v &p1,v &p2,v &p3) {
19 if((p2 - p1) * (p3 - p1) == 0) return p2 - p1 + p3;
20 if((p1 - p2) * (p3 - p2) == 0) return p1 - p2 + p3;
21 return p1 - p3 + p2;
22 }
23 inline void getv(v &k) {
24 scanf( " %d%d ",&k.x,&k.y);
25 }
26 int n,s,t,A,B; // the meaning of s will be changed in function "work"...
27 double dis[ 404][ 404]={ 0};
28 inline void makegragh() { // build dis[][]
29 v p[ 404];
30 int Ti;
31 for( int i= 1;i<=s;i+= 4) {
32 getv(p[i]),getv(p[i+ 1]),getv(p[i+ 2]);scanf( " %d ",&Ti);
33 p[i+ 3]=get4(p[i],p[i+ 1],p[i+ 2]);
34 for( int j= 0;j< 3;++j) for( int k=j;k< 4;++k)
35 dis[i+j][i+k]=dis[i+k][i+j]=Ti * mod((p[i+k]-p[i+j]));
36 for( int j= 1;j<i;++j) for( int k= 0;k< 4;++k)
37 dis[j][i+k]=dis[i+k][j]=t * mod((p[i+k]-p[j]));
38 }
39 }
40 inline double SPFA() {
41 deque < int> Q;
42 int k = 4 * A - 3,K = 4 * B - 3;
43 Q.push_front(k),Q.push_front(k+ 1),Q.push_front(k+ 2),Q.push_front(k+ 3);
44 bool in_Q[ 404] = { 0};in_Q[k]=in_Q[k+ 1]=in_Q[k+ 2]=in_Q[k+ 3]= 1;
45 double cost[ 404];
46 int i,t;
47 for(i= 1;i<=s;++i) cost[i] = MAX;
48 cost[k]=cost[k+ 1]=cost[k+ 2]=cost[k+ 3]= 0;
49 while(!Q.empty()) {
50 t = Q.front(); Q.pop_front(); in_Q[t] = 0;
51 for(i = 1;i <= s;++i) {
52 if(i==t) continue;
53 if(cost[i] > cost[t] + dis[i][t]) { // relax
54 cost[i] = cost[t] + dis[i][t];
55 if(in_Q[i]) continue;
56 if(Q.empty() || cost[Q.front()] < cost[i])Q.push_back(i);
57 else Q.push_front(i);
58 in_Q[i] = 1;
59 }
60 }
61 }
62 return min(min(cost[K],cost[K+ 1]),min(cost[K+ 2],cost[K+ 3]));
63 }
64 void work() {
65 scanf( " %d%d%d%d ",&s,&t,&A,&B);s *= 4; // s -> sum of airports
66 makegragh();
67 printf( " %.1f\n ", SPFA()); // (0) -> (4*n+1)
68 }
69 int main(){
70 #ifdef DEBUG
71 freopen( " test.in ", " r ",stdin);
72 #endif
73 scanf( " %d ",&n);
74 while(n--)
75 work();
76 return 0;
77 }