#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <deque>
using namespace std;
const int maxn=205;
const double E=1e-6;
double x[maxn],y[maxn],dis[maxn],ans=1e10;
int n,m,cnt,head[maxn],la[maxn];
bool vis[maxn];
struct Edge{int from,to,next;double val;}e[maxn*maxn/2+5];
double DIS(int a,int b){
return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
}
void A(int x,int y,double z){
e[++cnt].to=y;
e[cnt].val=z;
e[cnt].next=head[x];
e[cnt].from=x;
head[x]=cnt;
}
deque<int> q;//双端队列优化spfa,写习惯了
void spfa(bool st){//st是1则说明这次需要处理la数组记录最短路上的边,是0就不需记录
for(int i=1;i<=n;++i)dis[i]=1e10,vis[i]=0;
dis[1]=0;vis[1]=1;
q.push_back(1);
while(!q.empty()){
int x=q.front();q.pop_front();
vis[x]=0;
for(int i=head[x],y;i;i=e[i].next){
y=e[i].to;
if(dis[y]>dis[x]+e[i].val){
if(st)la[y]=i;//如果能被更新,说明这是目前最短路中的一条边
dis[y]=dis[x]+e[i].val;
if(!vis[y]){
vis[y]=1;
if(!q.empty()&&dis[y]<=dis[q.front()])q.push_front(y);//双端队列操作
else q.push_back(y);//双端队列操作
}
}
}
}
}
int main(){
// freopen("1.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)scanf("%lf%lf",&x[i],&y[i]);
double z;
for(int i=1,x,y;i<=m;++i){
scanf("%d%d",&x,&y);
z=DIS(x,y);
A(x,y,z);A(y,x,z);
}
spfa(1);
double res;
for(int i=la[n];i;i=la[e[i].from]){
res=e[i].val;//记录下要删掉边的权值,保存一下防丢
e[i].val=1e10;//删掉最短路中的一条边
spfa(0);
ans=min(ans,dis[n]);//记录,更新ans
e[i].val=res;//借助res,恢复这条边
}
if(ans==1e10)printf("-1\n");//1~n没有次短路
else printf("%.2lf\n",ans);
return 0;
}
原文:https://www.cnblogs.com/Lour688/p/13325189.html