次短路:最短路外的另一条最短路
两种次短路:
- 可经过重复顶点。
- 不可经过重复顶点。
如图所示
- 1->2->1->2->3
- 1->3
对于第一种次短路直接再加一个数组一起更新即可。
对于第二种次短路,需要记录下最短路的顶点,然后枚举这条路上的每一个相邻顶点,使得次短路不经过这两点之间的边。
#include <bits/stdc++.h>
using namespace std;
#define FOR0(a,b) for(int i = a; i < b; ++i)
#define FORE(a,b) for(int i = a; i <= b; ++i)
typedef long long ll;
typedef pair<int,double> pii;
const int maxn = 600;
struct Point{
int x,y;
}p[maxn];
vector<pii> G[maxn];
double dist(Point a, Point b) {
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void add(int u, int v, double w) {
G[u].push_back(pii(v,w));
}
int path[maxn],inq[maxn],n,m;
double d[maxn];
bool ok[maxn][maxn];
void spfa() {
queue<int> que;
for(int i = 1; i <= n; ++i)
d[i] = 100000000;
memset(inq,0,sizeof inq);
d[1] = 0;
inq[1] = true;
que.push(1);
while(!que.empty()) {
int u = que.front();
que.pop();
inq[u] = false;
// cout << G[u].size() << endl;
for(int i = 0; i < G[u].size(); ++i) {
int v = G[u][i].first;
double w = G[u][i].second;
if(!ok[u][v]) {
// cout << v << endl;
if(d[v] > d[u]+w) {
path[v] = u;
d[v] = d[u]+w;
if(!inq[v]) {
inq[v] = true;
que.push(v);
}
}
}
}
}
}
vector<int> shortp;
void getP(int x) {
while(x) {
shortp.push_back(x);
x = path[x];
}
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) {
scanf("%d%d", &p[i].x, &p[i].y);
}
for(int i = 0; i < m; ++i) {
int u,v;
scanf("%d%d", &u, &v);
add(u,v,dist(p[u],p[v]));
add(v,u,dist(p[u],p[v]));
}
spfa();
getP(n);
// cout << shortp.size() << " " << d[n] << endl;
if(shortp.size() == 0) {
puts("-1");
exit(0);
}
//puts("-2");
double ans = 100000000;
for(int i = 0; i < shortp.size()-1; ++i) {
int u = shortp[i], v = shortp[i+1];
ok[u][v] = ok[v][u] = true;
spfa();
ans = min(ans, d[n]);
ok[u][v] = ok[v][u] = false;
}
if(ans == 100000000)
puts("-1");
else printf("%.2lf\n", ans);
return 0;
}