计蒜客 迷阵突围

问题描述

蒜头君陷入了坐标系上的一个迷阵,迷阵上有 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;
}   

猜你喜欢

转载自blog.csdn.net/amf12345/article/details/89033336
今日推荐