您的位置:首页 > 其它

计蒜客习题:迷阵突围

2018-03-10 23:15 204 查看

问题描述

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

AC代码

原文传送门

#include<iostream>
#include<cstdio>
#include<set>
#include<vector>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn=207;
const int maxm=50007;   //207*207  可能有重边 所以再开大一些 不给数据范围是真的睿智
int n,m;
int x[maxn],y[maxn],fa[maxn],q[maxn];
double W(int u,int v);
struct edge{
int v,nxt;
double w;
}e[maxm<<1];        //睿智了 打成了maxn
int p[maxn],eid;
double dist[maxn];
double ans=99999999;
bool vst[maxn];
//int id[maxn][maxn];
typedef pair<double,int> pdi;
set<pdi,less<pdi> >min_heap;

void dijkstra(int a,int b);
void ins(int u,int v);
void ins2(int u,int v);
void init();
int main(){
cin>>n>>m;
init();
for(int i=1;i<=n;i++)
cin>>x[i]>>y[i];
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
ins2(a,b);
}
int now=n;
dijkstra(-1,-1);
while(fa[now]){
dijkstra(fa[now],now);
ans=min(dist
,ans);
now=fa[now];
}
if(ans==99999999) printf("-1");
else printf("%.2lf",ans);
return 0;
}
double W(int u,int v){return sqrt((x[u]-x[v])*(x[u]-x[v])+(y[u]-y[v])*(y[u]-y[v]));}
void dijkstra(int a,int b){
memset(vst,false,sizeof(vst));
for(int i=1;i<=n;i++) dist[i]=99999999;
dist[1]=0;
min_heap.insert(make_pair(0,1));
for(int i=1;i<=n;i++){
if(min_heap.size()==0) break;
auto iter=min_heap.begin();
int v=iter->second;
min_heap.erase(*iter);
if(vst[v]) continue;
vst[v]=true;
for(int j=p[v];j;j=e[j].nxt){   //枚举相邻边
if(v==a&&e[j].v==b||v==b&&e[j].v==a) continue;    //跳过最短路上的某条边
int x=e[j].v;
if(dist[x]>dist[v]+e[j].w){
min
b299
_heap.erase(make_pair(dist[x],x));
dist[x]=dist[v]+e[j].w;
min_heap.insert(make_pair(dist[x],x));
if(a==-1&&b==-1) fa[x]=v;
}
}
}

}
void ins(int u,int v){
e[++eid].v=v;
e[eid].nxt=p[u];
e[eid].w=W(u,v);
p[u]=eid;   //eid要从1开始  0开始会炸
}
void ins2(int u,int v){ins(u,v);ins(v,u);}  //无向边插两次
void init(){
eid=0;
memset(p,0,sizeof(p));
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: