题目链接
题目大意:给你s个城市,每个城市有四个机场,每个城市内机场两两之间有直达路径,所有城市内两两之间的机场都有可直达路径,问从a到b城市最短的路径是多少,出发点和结束点机场任选。
分析:思路大致就是对所有点建边,然后folyed或者四次单源最短路更新答案即可,关键点是建图。
然后问题关键要解决的就是矩形的第四个点怎么求,我们可以利用勾股定理,求出给定三点见两两之间的距离,然后判断哪条边是直角边,最后直接计算坐标即可。(具体看代码)
#include<bits/stdc++.h>
#define MAIN main
using namespace std;
typedef long long ll;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const int N=1e5+10;
int n,s,a,b;
double t;
int sgn(double x)
{
if(fabs(x)<eps) return 0;
return x>0?1:-1;
}
struct Point
{
double x,y;
int num;
Point (double x=0,double y=0,int num=0):x(x),y(y),num(num){
}
bool operator != (Point a){
return sgn(x-a.x)!=0&&sgn(y-a.y)!=0;
}
};
struct edge
{
int v,next;
double w;
}e[N<<1];
int head[N],cnt;
void add(int u,int v,double w)
{
e[++cnt].v=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt;
e[++cnt].v=u;
e[cnt].w=w;
e[cnt].next=head[v];
head[v]=cnt;
}
double Distance(Point a,Point b)
{
double d1=a.x-b.x;
double d2=a.y-b.y;
return sqrt(d1*d1+d2*d2);
}
struct node
{
Point p[4];
node(){
}
void build(double T)
{
for(int i=0;i<=3;i++){
for(int j=i+1;j<=3;j++){
add(p[i].num,p[j].num,T*Distance(p[i],p[j]));
}
}
}
};
node c[N];
void Add(node u,node v)
{
add(u.p[0].num,v.p[0].num,t*Distance(u.p[0],v.p[0]));
add(u.p[0].num,v.p[1].num,t*Distance(u.p[0],v.p[1]));
add(u.p[0].num,v.p[2].num,t*Distance(u.p[0],v.p[2]));
add(u.p[0].num,v.p[3].num,t*Distance(u.p[0],v.p[3]));
add(u.p[1].num,v.p[0].num,t*Distance(u.p[1],v.p[0]));
add(u.p[1].num,v.p[1].num,t*Distance(u.p[1],v.p[1]));
add(u.p[1].num,v.p[2].num,t*Distance(u.p[1],v.p[2]));
add(u.p[1].num,v.p[3].num,t*Distance(u.p[1],v.p[3]));
add(u.p[2].num,v.p[0].num,t*Distance(u.p[2],v.p[0]));
add(u.p[2].num,v.p[1].num,t*Distance(u.p[2],v.p[1]));
add(u.p[2].num,v.p[2].num,t*Distance(u.p[2],v.p[2]));
add(u.p[2].num,v.p[3].num,t*Distance(u.p[2],v.p[3]));
add(u.p[3].num,v.p[0].num,t*Distance(u.p[3],v.p[0]));
add(u.p[3].num,v.p[1].num,t*Distance(u.p[3],v.p[1]));
add(u.p[3].num,v.p[2].num,t*Distance(u.p[3],v.p[2]));
add(u.p[3].num,v.p[3].num,t*Distance(u.p[3],v.p[3]));
}
double dis[N];
int vis[N];
double ans;
void dijkstra(int ss)
{
priority_queue<pair<double,int> >q;
for(int i=1;i<=s*4;i++) vis[i]=0,dis[i]=1e10;
dis[ss]=0;
q.push(make_pair(-dis[ss],ss));
while(!q.empty())
{
int u=q.top().second;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w)
{
dis[v]=dis[u]+e[i].w;
q.push(make_pair(-dis[v],v));
}
}
}
ans=min(ans,dis[c[b].p[0].num]);
ans=min(ans,dis[c[b].p[1].num]);
ans=min(ans,dis[c[b].p[2].num]);
ans=min(ans,dis[c[b].p[3].num]);
}
int MAIN()
{
scanf("%d",&n);
while(n--)
{
scanf("%d%lf%d%d",&s,&t,&a,&b);
int num=0;
cnt=0;
memset(head,0,sizeof(head));
for(int i=1;i<=s;i++){
int x1,y1,x2,y2,x3,y3,T;
scanf("%d%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3,&T);
int x4,y4;
double ab=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
double ac=(x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
double bc=(x2-x3)*(x2-x3)+(y2-y3)*(y2-y3);
if(ab+ac==bc) x4=x2+x3-x1,y4=y2+y3-y1;
if(ab+bc==ac) x4=x1+x3-x2,y4=y1+y3-y2;
if(ac+bc==ab) x4=x1+x2-x3,y4=y1+y2-y3;
c[i].p[0]=Point(x1,y1,++num);
c[i].p[1]=Point(x2,y2,++num);
c[i].p[2]=Point(x3,y3,++num);
c[i].p[3]=Point(x4,y4,++num);
c[i].build(T);
}
for(int i=1;i<=s;i++){
for(int j=i+1;j<=s;j++){
Add(c[i],c[j]);
}
}
ans=1e20;
for(int i=0;i<=3;i++) dijkstra(c[a].p[i].num);
printf("%.1f\n",ans);
}
return 0;
}