题目描述
又到暑假了,住在城市 AA 的 CarCar 想和朋友一起去城市 BB 旅游。她知道每个城市都有 44 个飞机场,分别位于一个矩形的 44 个顶点上,同一个城市中 22 个机场之间有 11 条笔直的高速铁路,第 II 个城市中高速铁路了的单位里程价格为 T_iTi ,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为 tt 。
图例(从上而下)
机场
高速铁路
飞机航线
注意:图中并没有标出所有的铁路与航线。
那么 CarCar 应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
找出一条从城市 AA 到 BB 的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。
输入输出格式
输入格式:
第一行为一个正整数 nn ( 0 le n le 100≤n≤10 ),表示有 nn 组测试数据。
每组的第一行有 44 个正整数 s,t,A,Bs,t,A,B 。
SS ( 0<S le 1000<S≤100 )表示城市的个数, tt 表示飞机单位里程的价格, AA , BB 分别为城市 AA , BB 的序号,( 1 le A1≤A, B le SB≤S )。
接下来有 SS 行,其中第 II 行均有 77 个正整数 xi_1,yi_1,xi_2,yi_2,xi_3,yi_3,Tixi1,yi1,xi2,yi2,xi3,yi3,Ti ,这当中的( xi_1,yi_1xi1,yi1 ),( xi_2,yi_2xi2,yi2),( xi_3,yi_3xi3,yi3 )分别是第 ii 个城市中任意 33 个机场的坐标, TiTi 为第 ii 个城市高速铁路单位里程的价格。
输出格式:
共有 nn 行,每行 11 个数据对应测试数据。 保留一位小数。
输入输出样例
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
47.5
思路:转化成图之后跑spfa。
#include<cmath> #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; queue<int>que; int vis[410]; double ans=0x7f7f7f7f; int n,s,t,a,b,tot,sum; double cap[160010],dis[410]; int to[160010],net[160010],head[410]; struct nond{ int x[5],y[5],num[5]; double t; }v[110]; struct none{ int l,r; }; void add(int u,int v,double w){ to[++tot]=v;cap[tot]=w;net[tot]=head[u];head[u]=tot; to[++tot]=u;cap[tot]=w;net[tot]=head[v];head[v]=tot; } none find(int p){ none tmp; double maxn=-99999; for(int i=1;i<=3;i++) for(int j=i+1;j<=3;j++){ double x=(v[p].x[i]-v[p].x[j])*(v[p].x[i]-v[p].x[j])+(v[p].y[i]-v[p].y[j])*(v[p].y[i]-v[p].y[j]); if(x>maxn){ maxn=x; tmp.l=i;tmp.r=j; } } return tmp; } int findx(int p){ none tmp=find(p);int k; if(tmp.l==1&&tmp.r==2||tmp.l==2&&tmp.r==1) k=3; else if(tmp.l==1&&tmp.r==3||tmp.l==3&&tmp.r==1) k=2; else if(tmp.l==2&&tmp.r==3||tmp.l==3&&tmp.r==2) k=1; return v[p].x[tmp.l]+v[p].x[tmp.r]-v[p].x[k]; } int findy(int p){ none tmp=find(p);int k; if(tmp.l==1&&tmp.r==2||tmp.l==2&&tmp.r==1) k=3; else if(tmp.l==1&&tmp.r==3||tmp.l==3&&tmp.r==1) k=2; else if(tmp.l==2&&tmp.r==3||tmp.l==3&&tmp.r==2) k=1; return v[p].y[tmp.l]+v[p].y[tmp.r]-v[p].y[k]; } void build(){ for(int i=1;i<=s;i++){ for(int a=1;a<=4;a++){ for(int b=a+1;b<=4;b++){ double x=sqrt((v[i].x[a]-v[i].x[b])*(v[i].x[a]-v[i].x[b])+(v[i].y[a]-v[i].y[b])*(v[i].y[a]-v[i].y[b]))*v[i].t; add(v[i].num[a],v[i].num[b],x); } } for(int j=i+1;j<=s;j++) for(int a=1;a<=4;a++){ for(int b=1;b<=4;b++){ double x=t*sqrt((v[i].x[a]-v[j].x[b])*(v[i].x[a]-v[j].x[b])+(v[i].y[a]-v[j].y[b])*(v[i].y[a]-v[j].y[b])); add(v[i].num[a],v[j].num[b],x); } } } } void spfa(int s){ memset(vis,0,sizeof(vis)); memset(dis,0x7f,sizeof(dis)); while(!que.empty()) que.pop(); que.push(s);dis[s]=0;vis[s]=1; while(!que.empty()){ int now=que.front(); que.pop();vis[now]=0; for(int i=head[now];i;i=net[i]) if(dis[to[i]]>dis[now]+cap[i]){ dis[to[i]]=dis[now]+cap[i]; if(!vis[to[i]]){ vis[to[i]]=1; que.push(to[i]); } } } } int main(){ scanf("%d",&n); while(n--){ scanf("%d%d%d%d",&s,&t,&a,&b); for(int i=1;i<=s;i++){ int x1,y1,x2,y2,x3,y3,x4,y4,t; scanf("%d%d%d%d%d%d%lf",&v[i].x[1],&v[i].y[1],&v[i].x[2],&v[i].y[2],&v[i].x[3],&v[i].y[3],&v[i].t); v[i].x[4]=findx(i);v[i].y[4]=findy(i); for(int j=1;j<=4;j++) v[i].num[j]=++sum; } build(); for(int i=1;i<=4;i++){ spfa(v[a].num[i]); ans=min(ans,min(dis[v[b].num[1]],min(dis[v[b].num[2]],min(dis[v[b].num[3]],dis[v[b].num[4]])))); } printf("%.1lf",ans); ans=0x7f7f7f7; } }