问题描述
蒜头君陷入了坐标系上的一个迷阵,迷阵上有 n 个点,编号从 1 到 n。蒜头君在编号为 1 的位置,他想到编号为 n 的位置上。蒜头君当然想尽快到达目的地,但是他觉得最短的路径可能有风险,所以他会选择第二短的路径。现在蒜头君知道了 n 个点的坐标,以及哪些点之间是相连的,他想知道第二短的路径长度是多少。
注意,每条路径上不能重复经过同一个点。
输入格式
第一行输入两个整数 n (1≤n≤200) 和 m,表示一共有 n 个点和 m 条边。
接下来输入 n 行,每行输入两个整数xi,yi(−500≤xi,yi≤500),代表第 ii 个点的坐标。
接下来输入 mm 行,每行输入两个整数 pj,qj(1≤pj,qj≤n),表示点pj和点 qj之间相连。
输出格式
输出一行,输出包含一个数,表示第二短的路径长度(小数点后面保留两位),如果第一短路径有多条,则答案就是第一最短路径的长度;如果第二最短路径不存在,则输出 −1。
样例输入
3 3
1 1
2 2
3 2
1 2
2 3
1 3
样例输出
2.41
#include<bits/stdc++.h>
using namespace std;
const int MAX_N=205;
const int MAX_M=205*205;
double inf=1e10;
struct node{
double xx,yy;//(xx,yy)表示节点的坐标
}po[MAX_N];
double mp[MAX_N][MAX_N];
int vst[MAX_N];
int n,m;
double dst[MAX_N];
int fa[MAX_N];
double dd(int i,int j){
double xx=sqrt((po[i].xx-po[j].xx)*(po[i].xx-po[j].xx)+(po[i].yy-po[j].yy)*(po[i].yy-po[j].yy));
return xx;
}
void insert(int u,int v,double w){
mp[u][v]=mp[v][u]=w;
}
bool dijkstra(int s){
for(int i=1;i<=n;i++){
dst[i]=inf;
}
memset(fa,0,sizeof(fa));
memset(vst,0,sizeof(vst));
fa[s]=0;
dst[s]=0;
int ff=0;//标志
for(int i=1;i<=n;i++){
int v;
double minx=inf;
for(int j=1;j<=n;j++){
if(!vst[j]&&dst[j]<minx){
minx=dst[j];
v=j;
}
}
vst[v]=1;
if(v==n){
ff=1;
break;
}
for(int j=1;j<=n;j++){
if(!vst[j]&&mp[v][j]!=inf){
if(dst[v]+dd(v,j)<dst[j])
{
dst[j]=dst[v]+dd(v,j);
fa[j]=v;//更新最短路径与前驱
}
}
}
}
if(ff)
return true;
else
return false;
}
double dijkstra2(int s){
for(int i=1;i<=n;i++){
dst[i]=inf;
}
memset(vst,0,sizeof(vst));
dst[s]=0;
int ff=0;//标志
for(int i=1;i<=n;i++){
int v;
double minx=inf;
for(int j=1;j<=n;j++){
if(!vst[j]&&dst[j]<minx){
minx=dst[j];
v=j;
}
}
vst[v]=1;
if(v==n){
ff=1;
break;
}
for(int j=1;j<=n;j++){
if(!vst[j]&&mp[v][j]!=inf){
if(dst[v]+dd(v,j)<dst[j])
{
dst[j]=dst[v]+dd(v,j);
}
}
}
}
if(ff)
return dst[n];
else
return inf;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
mp[i][j]=inf;
}
}
double x,y;
for(int i=1;i<=n;i++){
cin>>x>>y;
po[i].xx=x;
po[i].yy=y;
}
int a,b;
for(int i=1;i<=m;i++){
scanf("%d%d",&a,&b);
double tt=dd(a,b);
insert(a,b,tt);
}
double val=inf;
if(dijkstra(1)){
int t1=fa[n],t2=n;
while(t1)
{
double ds=mp[t1][t2];
mp[t1][t2]=mp[t2][t1]=inf;
val=min(val,dijkstra2(1));
mp[t1][t2]=mp[t2][t1]=ds;
t2=t1;//标志为1表示已经在最短路中,次短路不能选
t1=fa[t1];
};
if(val==inf){
cout<<"-1"<<endl;
}else{
printf("%.2f\n",val);
}
}else{
cout<<"-1"<<endl;
}
return 0;
}