题目描述 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之后才想起来的=_=||
1 //Awsm.Definer →_→
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 ", 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 }
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 ", 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 }